@khanacademy/perseus 27.2.0 → 28.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/image-loader.d.ts +2 -2
- package/dist/components/{info-tip.d.ts → info-tip/index.d.ts} +2 -2
- package/dist/components/info-tip/info-tip-base.d.ts +6 -0
- package/dist/components.d.ts +0 -1
- package/dist/es/index.js +432 -340
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +6 -2
- package/dist/es/strings.js.map +1 -1
- package/dist/hints-renderer.d.ts +2 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +418 -326
- package/dist/index.js.map +1 -1
- package/dist/interactive2/movable-point.d.ts +3 -3
- package/dist/perseus-api.d.ts +3 -0
- package/dist/perseus-types.d.ts +10 -6
- package/dist/renderer.d.ts +2 -1
- package/dist/server-item-renderer.d.ts +3 -0
- package/dist/strings.d.ts +2 -0
- package/dist/strings.js +6 -2
- package/dist/strings.js.map +1 -1
- package/dist/types.d.ts +7 -7
- package/dist/util/{katex-preprocess.d.ts → tex-preprocess.d.ts} +1 -1
- package/dist/widgets/expression.d.ts +20 -2
- package/dist/widgets/interactive-graphs/graphs/angle.d.ts +7 -0
- package/dist/widgets/interactive-graphs/graphs/components/angle-indicators.d.ts +0 -2
- package/dist/widgets/interactive-graphs/graphs/components/movable-point.d.ts +3 -2
- package/dist/widgets/interactive-graphs/graphs/polygon.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/use-draggable.d.ts +7 -1
- package/dist/widgets/interactive-graphs/locked-figures/locked-function.d.ts +1 -1
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +1 -0
- package/dist/widgets/interactive-graphs/math/geometry.d.ts +2 -1
- package/dist/widgets/interactive-graphs/reducer/initialize-graph-state.d.ts +8 -1
- package/dist/widgets/interactive-graphs/reducer/use-graph-config.d.ts +1 -1
- package/dist/widgets/interactive-graphs/stateful-mafs-graph.d.ts +1 -0
- package/dist/widgets/label-image.d.ts +6 -0
- package/package.json +6 -6
- package/dist/components/info-tip/info-tip.d.ts +0 -6
- package/dist/components/prop-check-box.d.ts +0 -4
package/dist/es/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import * as PerseusLinter from '@khanacademy/perseus-linter';
|
|
|
5
5
|
import { linterContextDefault, Rule, linterContextProps } from '@khanacademy/perseus-linter';
|
|
6
6
|
import { View, RenderStateRoot, UniqueIDProvider, useLatestRef, useUniqueIdWithMock, Text as Text$2 } from '@khanacademy/wonder-blocks-core';
|
|
7
7
|
import Tooltip$1 from '@khanacademy/wonder-blocks-tooltip';
|
|
8
|
-
import { LabelSmall, Body, LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
8
|
+
import { HeadingMedium, LabelSmall, Body, LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
9
9
|
import { StyleSheet, css } from 'aphrodite';
|
|
10
10
|
import classNames from 'classnames';
|
|
11
11
|
import * as React from 'react';
|
|
@@ -17,13 +17,14 @@ import Clickable from '@khanacademy/wonder-blocks-clickable';
|
|
|
17
17
|
import { Popover, PopoverContentCore, PopoverContent } from '@khanacademy/wonder-blocks-popover';
|
|
18
18
|
import { color, spacing } from '@khanacademy/wonder-blocks-tokens';
|
|
19
19
|
import $ from 'jquery';
|
|
20
|
+
import { v4 } from 'uuid';
|
|
20
21
|
import PropTypes from 'prop-types';
|
|
21
22
|
import { number, point, vector as vector$1, line } from '@khanacademy/kmath';
|
|
22
23
|
import { entries, UnreachableCaseError, keys } from '@khanacademy/wonder-stuff-core';
|
|
23
24
|
import { CircularSpinner } from '@khanacademy/wonder-blocks-progress-spinner';
|
|
24
25
|
import SimpleMarkdown from '@khanacademy/simple-markdown';
|
|
25
26
|
import { pureMarkdownRules } from '@khanacademy/pure-markdown';
|
|
26
|
-
import { TextField
|
|
27
|
+
import { TextField } from '@khanacademy/wonder-blocks-form';
|
|
27
28
|
import Button from '@khanacademy/wonder-blocks-button';
|
|
28
29
|
import { Strut } from '@khanacademy/wonder-blocks-layout';
|
|
29
30
|
import Banner from '@khanacademy/wonder-blocks-banner';
|
|
@@ -34,11 +35,11 @@ import debounce$2 from 'lodash.debounce';
|
|
|
34
35
|
import { vec, Coordinates, Ellipse, Plot as Plot$3, Line as Line$4, Point as Point$2, Polygon, useTransformContext, Text as Text$1, Mafs } from 'mafs';
|
|
35
36
|
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
36
37
|
import questionIcon from '@phosphor-icons/core/regular/question.svg';
|
|
37
|
-
import createReactClass from 'create-react-class';
|
|
38
38
|
import { useDrag } from '@use-gesture/react';
|
|
39
39
|
import Switch from '@khanacademy/wonder-blocks-switch';
|
|
40
40
|
import Pill from '@khanacademy/wonder-blocks-pill';
|
|
41
41
|
import { Popper } from 'react-popper';
|
|
42
|
+
import createReactClass from 'create-react-class';
|
|
42
43
|
import Link from '@khanacademy/wonder-blocks-link';
|
|
43
44
|
|
|
44
45
|
function _extends() {
|
|
@@ -244,7 +245,9 @@ const mockStrings = {
|
|
|
244
245
|
loading: "Loading...",
|
|
245
246
|
videoTranscript: "See video transcript",
|
|
246
247
|
somethingWrong: "Something went wrong.",
|
|
247
|
-
videoWrapper: "Khan Academy video wrapper"
|
|
248
|
+
videoWrapper: "Khan Academy video wrapper",
|
|
249
|
+
mathInputTitle: "mathematics keyboard",
|
|
250
|
+
mathInputDescription: "Use keyboard/mouse to interact with math-based input fields"
|
|
248
251
|
};
|
|
249
252
|
|
|
250
253
|
/**
|
|
@@ -275,6 +278,26 @@ function PerseusI18nContextProvider({
|
|
|
275
278
|
}
|
|
276
279
|
const usePerseusI18n = () => useContext(PerseusI18nContext);
|
|
277
280
|
|
|
281
|
+
/*
|
|
282
|
+
* A11y (Accessibility) style rules
|
|
283
|
+
* These are used to mark up areas on the site that should only be readable
|
|
284
|
+
* when using a screen reader.
|
|
285
|
+
*/
|
|
286
|
+
var a11y = StyleSheet.create({
|
|
287
|
+
// Make content only visible to screen readers.
|
|
288
|
+
// Both collegeboard.org and Bootstrap 3 use this exact implementation.
|
|
289
|
+
srOnly: {
|
|
290
|
+
border: 0,
|
|
291
|
+
clip: "rect(0,0,0,0)",
|
|
292
|
+
height: 1,
|
|
293
|
+
margin: -1,
|
|
294
|
+
overflow: "hidden",
|
|
295
|
+
padding: 0,
|
|
296
|
+
position: "absolute",
|
|
297
|
+
width: 1
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
|
|
278
301
|
const debounce = (func, delay) => {
|
|
279
302
|
let timer = null;
|
|
280
303
|
return (...args) => {
|
|
@@ -472,11 +495,12 @@ class InnerMathInput extends React.Component {
|
|
|
472
495
|
"mq-editable-field": true,
|
|
473
496
|
"mq-math-mode": true
|
|
474
497
|
});
|
|
498
|
+
const popoverContentUniqueId = v4().slice(0, 8);
|
|
475
499
|
if (this.props.className) {
|
|
476
500
|
className = className + " " + this.props.className;
|
|
477
501
|
}
|
|
478
502
|
return /*#__PURE__*/React.createElement(View, {
|
|
479
|
-
style: [styles$
|
|
503
|
+
style: [styles$D.outerWrapper, this.state.focused && styles$D.wrapperFocused, this.props.hasError && styles$D.wrapperError]
|
|
480
504
|
}, /*#__PURE__*/React.createElement("div", {
|
|
481
505
|
style: {
|
|
482
506
|
display: "flex",
|
|
@@ -504,18 +528,23 @@ class InnerMathInput extends React.Component {
|
|
|
504
528
|
opened: this.state.keypadOpen,
|
|
505
529
|
onClose: () => this.closeKeypad(),
|
|
506
530
|
dismissEnabled: true,
|
|
531
|
+
"aria-label": this.context.strings.mathInputTitle,
|
|
532
|
+
"aria-describedby": `popover-content-${popoverContentUniqueId}`,
|
|
507
533
|
content: () => {
|
|
508
534
|
var _this$props$keypadBut, _this$props;
|
|
509
|
-
return /*#__PURE__*/React.createElement(
|
|
535
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(HeadingMedium, {
|
|
536
|
+
id: `popover-content-${popoverContentUniqueId}`,
|
|
537
|
+
style: a11y.srOnly
|
|
538
|
+
}, this.context.strings.mathInputDescription), /*#__PURE__*/React.createElement(PopoverContentCore, {
|
|
510
539
|
closeButtonVisible: true,
|
|
511
|
-
style: styles$
|
|
540
|
+
style: styles$D.popoverContent
|
|
512
541
|
}, /*#__PURE__*/React.createElement(DesktopKeypad, _extends({
|
|
513
542
|
onAnalyticsEvent: this.props.analytics.onAnalyticsEvent,
|
|
514
543
|
extraKeys: this.props.extraKeys,
|
|
515
544
|
onClickKey: this.handleKeypadPress,
|
|
516
545
|
cursorContext: this.state.cursorContext,
|
|
517
546
|
convertDotToTimes: this.props.convertDotToTimes
|
|
518
|
-
}, (_this$props$keypadBut = this.props.keypadButtonSets) != null ? _this$props$keypadBut : mapButtonSets((_this$props = this.props) == null ? void 0 : _this$props.buttonSets))));
|
|
547
|
+
}, (_this$props$keypadBut = this.props.keypadButtonSets) != null ? _this$props$keypadBut : mapButtonSets((_this$props = this.props) == null ? void 0 : _this$props.buttonSets)))));
|
|
519
548
|
}
|
|
520
549
|
}, this.props.buttonsVisible === "never" ? /*#__PURE__*/React.createElement(MathInputIcon, {
|
|
521
550
|
hovered: false,
|
|
@@ -584,9 +613,9 @@ const MathInputIcon = ({
|
|
|
584
613
|
fillColor = color.offBlack;
|
|
585
614
|
break;
|
|
586
615
|
}
|
|
587
|
-
const dynamicClass = active || focused ? styles$
|
|
616
|
+
const dynamicClass = active || focused ? styles$D.iconActive : styles$D.iconInactive;
|
|
588
617
|
return /*#__PURE__*/React.createElement(View, {
|
|
589
|
-
style: [styles$
|
|
618
|
+
style: [styles$D.iconContainer, dynamicClass]
|
|
590
619
|
}, /*#__PURE__*/React.createElement("svg", {
|
|
591
620
|
xmlns: "http://www.w3.org/2000/svg",
|
|
592
621
|
width: "16",
|
|
@@ -631,7 +660,7 @@ const inputFocused = {
|
|
|
631
660
|
borderColor: color.blue,
|
|
632
661
|
margin: -1
|
|
633
662
|
};
|
|
634
|
-
const styles$
|
|
663
|
+
const styles$D = StyleSheet.create({
|
|
635
664
|
iconContainer: {
|
|
636
665
|
display: "flex",
|
|
637
666
|
justifyContent: "center",
|
|
@@ -1161,26 +1190,6 @@ const ClassNames = {
|
|
|
1161
1190
|
MOBILE: "perseus-mobile"
|
|
1162
1191
|
};
|
|
1163
1192
|
|
|
1164
|
-
/*
|
|
1165
|
-
* A11y (Accessibility) style rules
|
|
1166
|
-
* These are used to mark up areas on the site that should only be readable
|
|
1167
|
-
* when using a screen reader.
|
|
1168
|
-
*/
|
|
1169
|
-
var a11y = StyleSheet.create({
|
|
1170
|
-
// Make content only visible to screen readers.
|
|
1171
|
-
// Both collegeboard.org and Bootstrap 3 use this exact implementation.
|
|
1172
|
-
srOnly: {
|
|
1173
|
-
border: 0,
|
|
1174
|
-
clip: "rect(0,0,0,0)",
|
|
1175
|
-
height: 1,
|
|
1176
|
-
margin: -1,
|
|
1177
|
-
overflow: "hidden",
|
|
1178
|
-
padding: 0,
|
|
1179
|
-
position: "absolute",
|
|
1180
|
-
width: 1
|
|
1181
|
-
}
|
|
1182
|
-
});
|
|
1183
|
-
|
|
1184
1193
|
const KhanMath = {
|
|
1185
1194
|
// Simplify formulas before display
|
|
1186
1195
|
cleanMath: function (expr) {
|
|
@@ -2475,7 +2484,7 @@ class Expression extends React.Component {
|
|
|
2475
2484
|
var _this$props$keypadCon, _this$props$analytics3;
|
|
2476
2485
|
if (this.props.apiOptions.customKeypad) {
|
|
2477
2486
|
return /*#__PURE__*/React.createElement(View, {
|
|
2478
|
-
className: css(styles$
|
|
2487
|
+
className: css(styles$C.mobileLabelInputWrapper)
|
|
2479
2488
|
}, !!this.props.visibleLabel && /*#__PURE__*/React.createElement(LabelSmall, {
|
|
2480
2489
|
htmlFor: this._textareaId,
|
|
2481
2490
|
tag: "label"
|
|
@@ -2510,7 +2519,7 @@ class Expression extends React.Component {
|
|
|
2510
2519
|
ERROR_TITLE
|
|
2511
2520
|
} = this.context.strings;
|
|
2512
2521
|
return /*#__PURE__*/React.createElement(View, {
|
|
2513
|
-
className: css(styles$
|
|
2522
|
+
className: css(styles$C.desktopLabelInputWrapper)
|
|
2514
2523
|
}, !!this.props.visibleLabel && /*#__PURE__*/React.createElement(LabelSmall, {
|
|
2515
2524
|
htmlFor: this._textareaId,
|
|
2516
2525
|
tag: "label"
|
|
@@ -2562,7 +2571,7 @@ Expression.defaultProps = {
|
|
|
2562
2571
|
apiOptions: ApiOptions.defaults,
|
|
2563
2572
|
linterContext: linterContextDefault
|
|
2564
2573
|
};
|
|
2565
|
-
const styles$
|
|
2574
|
+
const styles$C = StyleSheet.create({
|
|
2566
2575
|
mobileLabelInputWrapper: {
|
|
2567
2576
|
padding: "15px 4px 0"
|
|
2568
2577
|
},
|
|
@@ -8942,8 +8951,8 @@ function findChildOrAdd(elem, className) {
|
|
|
8942
8951
|
return $child;
|
|
8943
8952
|
}
|
|
8944
8953
|
var Tex$1 = {
|
|
8945
|
-
// Process a node and add math inside of it. This
|
|
8946
|
-
// format the math
|
|
8954
|
+
// Process a node and add math inside of it. This uses MathJax to
|
|
8955
|
+
// format the math.
|
|
8947
8956
|
//
|
|
8948
8957
|
// elem: The element which the math should be added to.
|
|
8949
8958
|
//
|
|
@@ -15305,7 +15314,7 @@ const DEFAULT_STATE$1 = {
|
|
|
15305
15314
|
// TODO(benchristel): this is a memory leak. We add items to
|
|
15306
15315
|
// tooltipResetFunctions, but never remove them.
|
|
15307
15316
|
const tooltipResetFunctions = [];
|
|
15308
|
-
class MovablePoint$
|
|
15317
|
+
class MovablePoint$5 {
|
|
15309
15318
|
constructor(graphie, movable, options) {
|
|
15310
15319
|
this.graphie = void 0;
|
|
15311
15320
|
this.movable = void 0;
|
|
@@ -15600,9 +15609,9 @@ class MovablePoint$4 {
|
|
|
15600
15609
|
* Displays a tooltip above the point, replacing any previous contents. If
|
|
15601
15610
|
* there is no tooltip initialized, adds the tooltip.
|
|
15602
15611
|
*
|
|
15603
|
-
* If the type of contents is string, the contents will be rendered
|
|
15604
|
-
*
|
|
15605
|
-
*
|
|
15612
|
+
* If the type of contents is string, the contents will be rendered as TeX
|
|
15613
|
+
* Otherwise, the content will be assumed to be a DOM node and will be
|
|
15614
|
+
* appended inside the tooltip.
|
|
15606
15615
|
*/
|
|
15607
15616
|
_showTooltip(contents) {
|
|
15608
15617
|
if (!this._tooltip) {
|
|
@@ -15823,15 +15832,15 @@ class MovablePoint$4 {
|
|
|
15823
15832
|
this.movable.toFront();
|
|
15824
15833
|
}
|
|
15825
15834
|
}
|
|
15826
|
-
MovablePoint$
|
|
15827
|
-
MovablePoint$
|
|
15828
|
-
MovablePoint$
|
|
15829
|
-
MovablePoint$
|
|
15830
|
-
MovablePoint$
|
|
15831
|
-
MovablePoint$
|
|
15832
|
-
MovablePoint$
|
|
15833
|
-
MovablePoint$
|
|
15834
|
-
MovablePoint$
|
|
15835
|
+
MovablePoint$5.add = MovablePointOptions.add;
|
|
15836
|
+
MovablePoint$5.modify = MovablePointOptions.modify;
|
|
15837
|
+
MovablePoint$5.draw = MovablePointOptions.draw;
|
|
15838
|
+
MovablePoint$5.remove = MovablePointOptions.remove;
|
|
15839
|
+
MovablePoint$5.onMoveStart = MovablePointOptions.onMoveStart;
|
|
15840
|
+
MovablePoint$5.constraints = MovablePointOptions.constraints;
|
|
15841
|
+
MovablePoint$5.onMove = MovablePointOptions.onMove;
|
|
15842
|
+
MovablePoint$5.onMoveEnd = MovablePointOptions.onMoveEnd;
|
|
15843
|
+
MovablePoint$5.onClick = MovablePointOptions.onClick;
|
|
15835
15844
|
function getKey(eventName, id) {
|
|
15836
15845
|
return eventName + ":" + id;
|
|
15837
15846
|
}
|
|
@@ -16425,10 +16434,10 @@ _.extend(MovablePolygon.prototype, {
|
|
|
16425
16434
|
});
|
|
16426
16435
|
|
|
16427
16436
|
const Interactive2 = {
|
|
16428
|
-
MovablePoint: MovablePoint$
|
|
16437
|
+
MovablePoint: MovablePoint$5,
|
|
16429
16438
|
addMovablePoint: function (graphie, options) {
|
|
16430
16439
|
const movable = new Movable(graphie, {});
|
|
16431
|
-
return new MovablePoint$
|
|
16440
|
+
return new MovablePoint$5(graphie, movable, options);
|
|
16432
16441
|
},
|
|
16433
16442
|
MovableLine: MovableLine$4,
|
|
16434
16443
|
addMovableLine: function (graphie, options) {
|
|
@@ -16469,7 +16478,7 @@ const Interactive2 = {
|
|
|
16469
16478
|
}
|
|
16470
16479
|
};
|
|
16471
16480
|
|
|
16472
|
-
const MovablePoint$
|
|
16481
|
+
const MovablePoint$4 = GraphieClasses.createClass({
|
|
16473
16482
|
displayName: "MovablePoint",
|
|
16474
16483
|
movableProps: ["children"],
|
|
16475
16484
|
_getProps: function () {
|
|
@@ -16526,7 +16535,7 @@ const MovablePoint$3 = GraphieClasses.createClass({
|
|
|
16526
16535
|
});
|
|
16527
16536
|
|
|
16528
16537
|
// Include helper methods, such as MovablePoint.constrain.snap()
|
|
16529
|
-
_.extend(MovablePoint$
|
|
16538
|
+
_.extend(MovablePoint$4, Interactive2.MovablePoint);
|
|
16530
16539
|
const MovableLine$3 = GraphieClasses.createClass({
|
|
16531
16540
|
displayName: "MovableLine",
|
|
16532
16541
|
movableProps: ["children"],
|
|
@@ -16696,7 +16705,7 @@ var Movables = {
|
|
|
16696
16705
|
Label: Label$1,
|
|
16697
16706
|
Line: Line$3,
|
|
16698
16707
|
MovableLine: MovableLine$3,
|
|
16699
|
-
MovablePoint: MovablePoint$
|
|
16708
|
+
MovablePoint: MovablePoint$4,
|
|
16700
16709
|
Parabola: Parabola,
|
|
16701
16710
|
Path: Path,
|
|
16702
16711
|
Plot: Plot$2,
|
|
@@ -17025,17 +17034,15 @@ class ImageLoader extends React.Component {
|
|
|
17025
17034
|
src,
|
|
17026
17035
|
imgProps
|
|
17027
17036
|
} = this.props;
|
|
17028
|
-
let onKeyUp
|
|
17029
|
-
let onKeyDown
|
|
17037
|
+
let onKeyUp;
|
|
17038
|
+
let onKeyDown;
|
|
17030
17039
|
if (imgProps.onClick != null) {
|
|
17031
|
-
// @ts-expect-error - TS2322 - Type '(e: React.KeyboardEvent) => void' is not assignable to type 'null'.
|
|
17032
17040
|
onKeyUp = e => {
|
|
17033
17041
|
// 13 is enter key, 32 is space key
|
|
17034
17042
|
if (e.keyCode === 13 || e.keyCode === 32) {
|
|
17035
17043
|
imgProps.onClick && imgProps.onClick(e);
|
|
17036
17044
|
}
|
|
17037
17045
|
};
|
|
17038
|
-
// @ts-expect-error - TS2322 - Type '(e: React.KeyboardEvent) => void' is not assignable to type 'null'.
|
|
17039
17046
|
onKeyDown = e => {
|
|
17040
17047
|
// 32 is space key
|
|
17041
17048
|
if (e.keyCode === 32) {
|
|
@@ -17046,12 +17053,8 @@ class ImageLoader extends React.Component {
|
|
|
17046
17053
|
}
|
|
17047
17054
|
const staticUrl = getDependencies().staticUrl;
|
|
17048
17055
|
return /*#__PURE__*/React.createElement("img", _extends({
|
|
17049
|
-
src: staticUrl(src)
|
|
17050
|
-
|
|
17051
|
-
,
|
|
17052
|
-
onKeyUp: onKeyUp
|
|
17053
|
-
// @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'KeyboardEventHandler<HTMLImageElement> | undefined'.
|
|
17054
|
-
,
|
|
17056
|
+
src: staticUrl(src),
|
|
17057
|
+
onKeyUp: onKeyUp,
|
|
17055
17058
|
onKeyDown: onKeyDown
|
|
17056
17059
|
}, imgProps));
|
|
17057
17060
|
};
|
|
@@ -17549,18 +17552,14 @@ class SvgImage extends React.Component {
|
|
|
17549
17552
|
allowFullBleed: this.props.allowFullBleed && isImageProbablyPhotograph(imageSrc)
|
|
17550
17553
|
}, /*#__PURE__*/React.createElement(ImageLoader, {
|
|
17551
17554
|
src: imageSrc,
|
|
17552
|
-
imgProps: imageProps
|
|
17553
|
-
// @ts-expect-error - TS2322 - Type '(() => Element) | null' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>> | null | undefined'.
|
|
17554
|
-
,
|
|
17555
|
+
imgProps: imageProps,
|
|
17555
17556
|
preloader: preloader,
|
|
17556
17557
|
onUpdate: this.handleUpdate
|
|
17557
17558
|
}), extraGraphie);
|
|
17558
17559
|
}
|
|
17559
17560
|
imageProps.style = dimensions;
|
|
17560
17561
|
return /*#__PURE__*/React.createElement(ImageLoader, {
|
|
17561
|
-
src: imageSrc
|
|
17562
|
-
// @ts-expect-error - TS2322 - Type '(() => Element) | null' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>> | null | undefined'.
|
|
17563
|
-
,
|
|
17562
|
+
src: imageSrc,
|
|
17564
17563
|
preloader: preloader,
|
|
17565
17564
|
imgProps: imageProps,
|
|
17566
17565
|
onUpdate: this.handleUpdate
|
|
@@ -17610,9 +17609,7 @@ class SvgImage extends React.Component {
|
|
|
17610
17609
|
}, /*#__PURE__*/React.createElement(ImageLoader, {
|
|
17611
17610
|
src: imageUrl,
|
|
17612
17611
|
onLoad: this.onImageLoad,
|
|
17613
|
-
onUpdate: this.handleUpdate
|
|
17614
|
-
// @ts-expect-error - TS2322 - Type '(() => Element) | null' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>> | null | undefined'.
|
|
17615
|
-
,
|
|
17612
|
+
onUpdate: this.handleUpdate,
|
|
17616
17613
|
preloader: preloader,
|
|
17617
17614
|
imgProps: imageProps
|
|
17618
17615
|
}), graphie, extraGraphie);
|
|
@@ -17624,9 +17621,7 @@ class SvgImage extends React.Component {
|
|
|
17624
17621
|
}, /*#__PURE__*/React.createElement(ImageLoader, {
|
|
17625
17622
|
src: imageUrl,
|
|
17626
17623
|
onLoad: this.onImageLoad,
|
|
17627
|
-
onUpdate: this.handleUpdate
|
|
17628
|
-
// @ts-expect-error - TS2322 - Type '(() => Element) | null' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>> | null | undefined'.
|
|
17629
|
-
,
|
|
17624
|
+
onUpdate: this.handleUpdate,
|
|
17630
17625
|
preloader: preloader,
|
|
17631
17626
|
imgProps: imageProps
|
|
17632
17627
|
}), graphie);
|
|
@@ -18199,33 +18194,33 @@ class Lint extends React.Component {
|
|
|
18199
18194
|
let warningText;
|
|
18200
18195
|
let warningTextStyle;
|
|
18201
18196
|
if (this.props.severity === Severity.Error) {
|
|
18202
|
-
severityStyle = styles$
|
|
18197
|
+
severityStyle = styles$B.indicatorError;
|
|
18203
18198
|
warningText = "Error";
|
|
18204
|
-
warningTextStyle = styles$
|
|
18199
|
+
warningTextStyle = styles$B.publishBlockingError;
|
|
18205
18200
|
} else if (this.props.severity === Severity.Warning) {
|
|
18206
|
-
severityStyle = styles$
|
|
18201
|
+
severityStyle = styles$B.indicatorWarning;
|
|
18207
18202
|
warningText = "Warning";
|
|
18208
|
-
warningTextStyle = styles$
|
|
18203
|
+
warningTextStyle = styles$B.warning;
|
|
18209
18204
|
} else {
|
|
18210
|
-
severityStyle = styles$
|
|
18205
|
+
severityStyle = styles$B.indicatorGuideline;
|
|
18211
18206
|
warningText = "Recommendation";
|
|
18212
|
-
warningTextStyle = styles$
|
|
18207
|
+
warningTextStyle = styles$B.warning;
|
|
18213
18208
|
}
|
|
18214
18209
|
return /*#__PURE__*/React.createElement("a", {
|
|
18215
18210
|
href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
|
|
18216
18211
|
target: "lint-help-window",
|
|
18217
18212
|
className: css(style)
|
|
18218
18213
|
}, /*#__PURE__*/React.createElement("span", {
|
|
18219
|
-
className: css(styles$
|
|
18214
|
+
className: css(styles$B.indicator, severityStyle)
|
|
18220
18215
|
}, this.props.severity === 1 && /*#__PURE__*/React.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React.createElement("div", {
|
|
18221
|
-
className: css(styles$
|
|
18216
|
+
className: css(styles$B.tooltip, tooltipAbove && styles$B.tooltipAbove)
|
|
18222
18217
|
}, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React.createElement("p", {
|
|
18223
18218
|
key: i,
|
|
18224
|
-
className: css(styles$
|
|
18219
|
+
className: css(styles$B.tooltipParagraph)
|
|
18225
18220
|
}, /*#__PURE__*/React.createElement("span", {
|
|
18226
18221
|
className: css(warningTextStyle)
|
|
18227
18222
|
}, warningText, ":", " "), m)), /*#__PURE__*/React.createElement("div", {
|
|
18228
|
-
className: css(styles$
|
|
18223
|
+
className: css(styles$B.tail, tooltipAbove && styles$B.tailAbove)
|
|
18229
18224
|
})));
|
|
18230
18225
|
};
|
|
18231
18226
|
}
|
|
@@ -18263,20 +18258,20 @@ class Lint extends React.Component {
|
|
|
18263
18258
|
}
|
|
18264
18259
|
if (blockHighlight) {
|
|
18265
18260
|
return /*#__PURE__*/React.createElement("span", {
|
|
18266
|
-
className: css(styles$
|
|
18267
|
-
}, this.renderLink(styles$
|
|
18261
|
+
className: css(styles$B.lintContainer, styles$B.lintContainerBlock)
|
|
18262
|
+
}, this.renderLink(styles$B.radioWidgetHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
|
|
18268
18263
|
}
|
|
18269
18264
|
if (inline) {
|
|
18270
18265
|
return /*#__PURE__*/React.createElement("span", {
|
|
18271
|
-
className: css(styles$
|
|
18272
|
-
}, this.renderLink(styles$
|
|
18266
|
+
className: css(styles$B.lintContainer)
|
|
18267
|
+
}, this.renderLink(styles$B.inlineHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
|
|
18273
18268
|
}
|
|
18274
18269
|
return /*#__PURE__*/React.createElement("div", {
|
|
18275
|
-
className: css(styles$
|
|
18276
|
-
}, this.renderLink(styles$
|
|
18270
|
+
className: css(styles$B.lintContainer)
|
|
18271
|
+
}, this.renderLink(styles$B.hoverTarget), /*#__PURE__*/React.createElement("div", null, children));
|
|
18277
18272
|
}
|
|
18278
18273
|
}
|
|
18279
|
-
const styles$
|
|
18274
|
+
const styles$B = StyleSheet.create({
|
|
18280
18275
|
// This is the class of the outermost element.
|
|
18281
18276
|
// We use relative positioning so that the lint indicator can be
|
|
18282
18277
|
// positioned absolutely relative to the position of the linty container.
|
|
@@ -18953,15 +18948,17 @@ class TranslationLinter {
|
|
|
18953
18948
|
}
|
|
18954
18949
|
|
|
18955
18950
|
/**
|
|
18956
|
-
* Preprocess TeX code to convert things that
|
|
18951
|
+
* Preprocess TeX code to convert things that MathJax doesn't know how to handle
|
|
18957
18952
|
* to things is does.
|
|
18958
18953
|
*/
|
|
18959
|
-
|
|
18960
18954
|
var preprocessTex = (texCode => texCode
|
|
18961
18955
|
// Replace uses of \begin{align}...\end{align} which KaTeX doesn't
|
|
18962
18956
|
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
18963
18957
|
// the same is supported by KaTeX. It does the same for align*.
|
|
18964
18958
|
// TODO(kevinb) update content to use aligned instead of align.
|
|
18959
|
+
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
18960
|
+
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
18961
|
+
// "aligned").
|
|
18965
18962
|
.replace(/\{align[*]?\}/g, "{aligned}")
|
|
18966
18963
|
// Replace non-breaking spaces with regular spaces.
|
|
18967
18964
|
.replace(/[\u00a0]/g, " "));
|
|
@@ -20211,7 +20208,7 @@ class Renderer extends React.Component {
|
|
|
20211
20208
|
paddingLeft: margin,
|
|
20212
20209
|
paddingRight: margin
|
|
20213
20210
|
};
|
|
20214
|
-
const mobileInnerStyle = _extends({}, innerStyle, styles$
|
|
20211
|
+
const mobileInnerStyle = _extends({}, innerStyle, styles$A.mobileZoomableParentFix);
|
|
20215
20212
|
return /*#__PURE__*/React.createElement("div", {
|
|
20216
20213
|
key: state.key,
|
|
20217
20214
|
className: "perseus-block-math",
|
|
@@ -20238,6 +20235,9 @@ class Renderer extends React.Component {
|
|
|
20238
20235
|
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
20239
20236
|
// the same is supported by KaTeX. It does the same for align*.
|
|
20240
20237
|
// TODO(kevinb) update content to use aligned instead of align.
|
|
20238
|
+
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
20239
|
+
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
20240
|
+
// "aligned").
|
|
20241
20241
|
const tex = node.content.replace(/\{align[*]?\}/g, "{aligned}");
|
|
20242
20242
|
|
|
20243
20243
|
// We render math here instead of in perseus-markdown.jsx
|
|
@@ -20332,7 +20332,7 @@ class Renderer extends React.Component {
|
|
|
20332
20332
|
paddingLeft: 0,
|
|
20333
20333
|
paddingRight: 0
|
|
20334
20334
|
};
|
|
20335
|
-
const mobileInnerStyle = _extends({}, innerStyle, styles$
|
|
20335
|
+
const mobileInnerStyle = _extends({}, innerStyle, styles$A.mobileZoomableParentFix);
|
|
20336
20336
|
const wrappedOutput = /*#__PURE__*/React.createElement("div", {
|
|
20337
20337
|
style: _extends({}, mobileInnerStyle, {
|
|
20338
20338
|
overflowX: "auto"
|
|
@@ -20981,7 +20981,7 @@ Renderer.defaultProps = {
|
|
|
20981
20981
|
onSerializedStateUpdated: () => {},
|
|
20982
20982
|
linterContext: PerseusLinter.linterContextDefault
|
|
20983
20983
|
};
|
|
20984
|
-
const styles$
|
|
20984
|
+
const styles$A = {
|
|
20985
20985
|
mobileZoomableParentFix: {
|
|
20986
20986
|
// NOTE(abdul): There is an issue where transform animations will
|
|
20987
20987
|
// cause the Zoomable component to disappear when running on the
|
|
@@ -21855,10 +21855,10 @@ class InputNumber extends React.Component {
|
|
|
21855
21855
|
// Note: This is _very_ similar to what `numeric-input.jsx` does. If
|
|
21856
21856
|
// you modify this, double-check if you also need to modify that
|
|
21857
21857
|
// component.
|
|
21858
|
-
const inputStyles = [styles$
|
|
21858
|
+
const inputStyles = [styles$z.default, this.props.size === "small" ? styles$z.small : null, this.props.rightAlign ? styles$z.rightAlign : styles$z.leftAlign];
|
|
21859
21859
|
// Unanswered
|
|
21860
21860
|
if (rubric && !this.props.currentValue) {
|
|
21861
|
-
inputStyles.push(styles$
|
|
21861
|
+
inputStyles.push(styles$z.answerStateUnanswered);
|
|
21862
21862
|
}
|
|
21863
21863
|
return /*#__PURE__*/React.createElement(InputWithExamples
|
|
21864
21864
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -21943,7 +21943,7 @@ InputNumber.defaultProps = {
|
|
|
21943
21943
|
apiOptions: ApiOptions.defaults,
|
|
21944
21944
|
linterContext: linterContextDefault
|
|
21945
21945
|
};
|
|
21946
|
-
const styles$
|
|
21946
|
+
const styles$z = StyleSheet.create({
|
|
21947
21947
|
default: {
|
|
21948
21948
|
width: 80,
|
|
21949
21949
|
height: "auto"
|
|
@@ -22938,7 +22938,7 @@ const FocusRing = function FocusRing(props) {
|
|
|
22938
22938
|
};
|
|
22939
22939
|
return /*#__PURE__*/React.createElement("span", {
|
|
22940
22940
|
"data-testid": "focus-ring",
|
|
22941
|
-
className: css(styles$
|
|
22941
|
+
className: css(styles$y.ring),
|
|
22942
22942
|
style: style
|
|
22943
22943
|
}, children);
|
|
22944
22944
|
};
|
|
@@ -22947,7 +22947,7 @@ FocusRing.defaultProps = {
|
|
|
22947
22947
|
color: kaGreen$1,
|
|
22948
22948
|
multipleSelect: false
|
|
22949
22949
|
};
|
|
22950
|
-
const styles$
|
|
22950
|
+
const styles$y = StyleSheet.create({
|
|
22951
22951
|
ring: {
|
|
22952
22952
|
margin: "auto",
|
|
22953
22953
|
display: "inline-block",
|
|
@@ -22974,7 +22974,7 @@ function getChoiceLetter(pos, strings) {
|
|
|
22974
22974
|
}
|
|
22975
22975
|
|
|
22976
22976
|
const CHOICE_ICON_SIZE = 24;
|
|
22977
|
-
const styles$
|
|
22977
|
+
const styles$x = StyleSheet.create({
|
|
22978
22978
|
iconWrapper: {
|
|
22979
22979
|
display: "inline-block",
|
|
22980
22980
|
position: "relative"
|
|
@@ -22997,7 +22997,7 @@ const CrossOutLine = function CrossOutLine(props) {
|
|
|
22997
22997
|
width: CROSS_OUT_LINE_SIZE,
|
|
22998
22998
|
height: CROSS_OUT_LINE_SIZE,
|
|
22999
22999
|
viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
|
|
23000
|
-
className: css(styles$
|
|
23000
|
+
className: css(styles$w.crossOutLine),
|
|
23001
23001
|
"data-testid": "choice-icon__cross-out-line"
|
|
23002
23002
|
}, /*#__PURE__*/React.createElement("line", {
|
|
23003
23003
|
// The line stretches from the bottom-left to top-right.
|
|
@@ -23012,7 +23012,7 @@ const CrossOutLine = function CrossOutLine(props) {
|
|
|
23012
23012
|
strokeLinecap: "round"
|
|
23013
23013
|
}));
|
|
23014
23014
|
};
|
|
23015
|
-
const styles$
|
|
23015
|
+
const styles$w = StyleSheet.create({
|
|
23016
23016
|
crossOutLine: {
|
|
23017
23017
|
// Center the icon within the container.
|
|
23018
23018
|
position: "absolute",
|
|
@@ -23096,7 +23096,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
23096
23096
|
} = props;
|
|
23097
23097
|
const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
|
|
23098
23098
|
return /*#__PURE__*/React.createElement("div", {
|
|
23099
|
-
className: css(styles$
|
|
23099
|
+
className: css(styles$x.iconWrapper)
|
|
23100
23100
|
}, /*#__PURE__*/React.createElement(FocusRing, {
|
|
23101
23101
|
color: color.blue,
|
|
23102
23102
|
visible: focused || hovered,
|
|
@@ -23105,13 +23105,13 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
23105
23105
|
// @ts-expect-error - TS2322 - Type '{ backgroundColor: string | null | undefined; borderColor: string; color: string; borderRadius: number; }' is not assignable to type 'Properties<string | number, string & {}>'.
|
|
23106
23106
|
style: dynamicStyles,
|
|
23107
23107
|
"data-testid": "choice-icon__library-choice-icon",
|
|
23108
|
-
className: css(styles$
|
|
23108
|
+
className: css(styles$v.circle, showCorrectness && correct && styles$v.circleCorrect, showCorrectness && !correct && styles$v.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$v.circleIncorrectAnswered)
|
|
23109
23109
|
// used in BaseRadio editMode to check
|
|
23110
23110
|
// if we actually clicked on the radio icon
|
|
23111
23111
|
,
|
|
23112
23112
|
"data-is-radio-icon": true
|
|
23113
23113
|
}, /*#__PURE__*/React.createElement("div", {
|
|
23114
|
-
className: css(styles$
|
|
23114
|
+
className: css(styles$v.innerWrapper)
|
|
23115
23115
|
}, /*#__PURE__*/React.createElement(ChoiceInner, {
|
|
23116
23116
|
pos: pos,
|
|
23117
23117
|
showCorrectness: showCorrectness,
|
|
@@ -23120,7 +23120,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
23120
23120
|
color: dynamicStyles.borderColor
|
|
23121
23121
|
}));
|
|
23122
23122
|
};
|
|
23123
|
-
const styles$
|
|
23123
|
+
const styles$v = StyleSheet.create({
|
|
23124
23124
|
innerWrapper: {
|
|
23125
23125
|
width: CHOICE_ICON_SIZE,
|
|
23126
23126
|
height: CHOICE_ICON_SIZE,
|
|
@@ -23215,19 +23215,19 @@ const OptionStatus = function OptionStatus(props) {
|
|
|
23215
23215
|
}
|
|
23216
23216
|
let textStyle;
|
|
23217
23217
|
if (correct) {
|
|
23218
|
-
textStyle = styles$
|
|
23218
|
+
textStyle = styles$u.correct;
|
|
23219
23219
|
} else {
|
|
23220
23220
|
if (checked || previouslyAnswered) {
|
|
23221
|
-
textStyle = styles$
|
|
23221
|
+
textStyle = styles$u.incorrectAnswered;
|
|
23222
23222
|
} else {
|
|
23223
|
-
textStyle = styles$
|
|
23223
|
+
textStyle = styles$u.incorrect;
|
|
23224
23224
|
}
|
|
23225
23225
|
}
|
|
23226
23226
|
return /*#__PURE__*/React.createElement("div", {
|
|
23227
|
-
className: css(styles$
|
|
23227
|
+
className: css(styles$u.text, textStyle)
|
|
23228
23228
|
}, renderText(checked, correct, crossedOut, strings));
|
|
23229
23229
|
};
|
|
23230
|
-
const styles$
|
|
23230
|
+
const styles$u = StyleSheet.create({
|
|
23231
23231
|
text: {
|
|
23232
23232
|
alignItems: "center",
|
|
23233
23233
|
display: "flex",
|
|
@@ -23297,8 +23297,8 @@ const Choice = function Choice(props) {
|
|
|
23297
23297
|
crossedOut: updatedCrossedOut
|
|
23298
23298
|
});
|
|
23299
23299
|
}
|
|
23300
|
-
const descriptionClassName = classNames("description", css(styles$
|
|
23301
|
-
const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$
|
|
23300
|
+
const descriptionClassName = classNames("description", css(styles$t.description));
|
|
23301
|
+
const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$t.rationale));
|
|
23302
23302
|
|
|
23303
23303
|
// We want to show the choices as dimmed out when the choices are disabled.
|
|
23304
23304
|
// However, we don't want to do this when we're in review mode in the
|
|
@@ -23458,7 +23458,7 @@ const Choice = function Choice(props) {
|
|
|
23458
23458
|
"data-testid": `perseus-radio-rationale-content-${pos}`
|
|
23459
23459
|
}, rationale));
|
|
23460
23460
|
};
|
|
23461
|
-
const styles$
|
|
23461
|
+
const styles$t = StyleSheet.create({
|
|
23462
23462
|
description: {
|
|
23463
23463
|
display: "inline-block",
|
|
23464
23464
|
width: "100%"
|
|
@@ -23657,10 +23657,10 @@ const BaseRadio = function BaseRadio(props) {
|
|
|
23657
23657
|
const isMobile = apiOptions.isMobile;
|
|
23658
23658
|
const firstChoiceHighlighted = choices[0].highlighted;
|
|
23659
23659
|
const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
|
|
23660
|
-
const className = classNames("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$
|
|
23661
|
-
const instructionsClassName = classNames("instructions", css(styles$
|
|
23660
|
+
const className = classNames("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$s.radio, styles$s.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$s.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$s.radioContainerLastHighlighted));
|
|
23661
|
+
const instructionsClassName = classNames("instructions", css(styles$s.instructions, isMobile && styles$s.instructionsMobile));
|
|
23662
23662
|
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect, strings);
|
|
23663
|
-
const responsiveClassName = css(styles$
|
|
23663
|
+
const responsiveClassName = css(styles$s.responsiveFieldset);
|
|
23664
23664
|
const fieldset = /*#__PURE__*/React.createElement("fieldset", {
|
|
23665
23665
|
className: `perseus-widget-radio-fieldset ${responsiveClassName}`
|
|
23666
23666
|
}, /*#__PURE__*/React.createElement("legend", {
|
|
@@ -23711,7 +23711,7 @@ const BaseRadio = function BaseRadio(props) {
|
|
|
23711
23711
|
const aphroditeClassName = checked => {
|
|
23712
23712
|
// Whether or not to show correctness borders
|
|
23713
23713
|
// for this choice and the next choice.
|
|
23714
|
-
return css(sharedStyles.aboveScratchpad, styles$
|
|
23714
|
+
return css(sharedStyles.aboveScratchpad, styles$s.item, styles$s.responsiveItem, checked && styles$s.selectedItem, checked && choice.highlighted && styles$s.aboveBackdrop, checked && choice.highlighted && apiOptions.isMobile && styles$s.aboveBackdropMobile, nextChoiceHighlighted && apiOptions.isMobile && styles$s.nextHighlighted);
|
|
23715
23715
|
};
|
|
23716
23716
|
|
|
23717
23717
|
// HACK(abdulrahman): Preloads the selection-state
|
|
@@ -23785,14 +23785,14 @@ const BaseRadio = function BaseRadio(props) {
|
|
|
23785
23785
|
// Allow for horizontal scrolling if content is too wide, which may be
|
|
23786
23786
|
// an issue especially on phones.
|
|
23787
23787
|
return /*#__PURE__*/React.createElement("div", {
|
|
23788
|
-
className: css(styles$
|
|
23788
|
+
className: css(styles$s.responsiveContainer)
|
|
23789
23789
|
}, fieldset);
|
|
23790
23790
|
};
|
|
23791
23791
|
BaseRadio.defaultProps = {
|
|
23792
23792
|
editMode: false,
|
|
23793
23793
|
multipleSelect: false
|
|
23794
23794
|
};
|
|
23795
|
-
const styles$
|
|
23795
|
+
const styles$s = StyleSheet.create({
|
|
23796
23796
|
instructions: {
|
|
23797
23797
|
display: "block",
|
|
23798
23798
|
color: gray17,
|
|
@@ -24454,9 +24454,9 @@ class Categorizer extends React.Component {
|
|
|
24454
24454
|
indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
|
|
24455
24455
|
}
|
|
24456
24456
|
const table = /*#__PURE__*/React.createElement("table", {
|
|
24457
|
-
className: "categorizer-table " + css(styles$
|
|
24457
|
+
className: "categorizer-table " + css(styles$r.mobileTable)
|
|
24458
24458
|
}, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
|
|
24459
|
-
className: css(styles$
|
|
24459
|
+
className: css(styles$r.emptyHeaderCell)
|
|
24460
24460
|
}), this.props.categories.map((category, i) => {
|
|
24461
24461
|
// Array index is the correct key here, as that's
|
|
24462
24462
|
// how category grading actually works -- no way
|
|
@@ -24464,7 +24464,7 @@ class Categorizer extends React.Component {
|
|
|
24464
24464
|
// middle. (If we later add that, this should be
|
|
24465
24465
|
// fixed.)
|
|
24466
24466
|
return /*#__PURE__*/React.createElement("th", {
|
|
24467
|
-
className: css(styles$
|
|
24467
|
+
className: css(styles$r.header),
|
|
24468
24468
|
key: i
|
|
24469
24469
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
24470
24470
|
content: category,
|
|
@@ -24486,7 +24486,7 @@ class Categorizer extends React.Component {
|
|
|
24486
24486
|
})), self.props.categories.map((catName, catNum) => {
|
|
24487
24487
|
const selected = self.props.values[itemNum] === catNum;
|
|
24488
24488
|
return /*#__PURE__*/React.createElement("td", {
|
|
24489
|
-
className: "category " + css(styles$
|
|
24489
|
+
className: "category " + css(styles$r.cell),
|
|
24490
24490
|
key: catNum
|
|
24491
24491
|
}, /*#__PURE__*/React.createElement("div", {
|
|
24492
24492
|
className: ClassNames.INTERACTIVE,
|
|
@@ -24501,7 +24501,7 @@ class Categorizer extends React.Component {
|
|
|
24501
24501
|
onChange: () => this.onChange(itemNum, catNum),
|
|
24502
24502
|
onClick: e => e.stopPropagation()
|
|
24503
24503
|
}), !isMobile && /*#__PURE__*/React.createElement("span", {
|
|
24504
|
-
className: css(styles$
|
|
24504
|
+
className: css(styles$r.radioSpan, selected && styles$r.checkedRadioSpan, this.props.static && selected && styles$r.staticCheckedRadioSpan)
|
|
24505
24505
|
}, selected ? /*#__PURE__*/React.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React.createElement(InlineIcon, iconCircleThin))));
|
|
24506
24506
|
}));
|
|
24507
24507
|
/* eslint-enable max-len */
|
|
@@ -24513,7 +24513,7 @@ class Categorizer extends React.Component {
|
|
|
24513
24513
|
"categorizer-container": true,
|
|
24514
24514
|
"static-mode": this.props.static
|
|
24515
24515
|
});
|
|
24516
|
-
const inlineStyles = this.props.apiOptions.isMobile ? [styles$
|
|
24516
|
+
const inlineStyles = this.props.apiOptions.isMobile ? [styles$r.fullBleedContainer] : [];
|
|
24517
24517
|
return /*#__PURE__*/React.createElement("div", {
|
|
24518
24518
|
className: extraClassNames + " " + css(...inlineStyles)
|
|
24519
24519
|
}, table);
|
|
@@ -24566,7 +24566,7 @@ const pageMargin = 16;
|
|
|
24566
24566
|
|
|
24567
24567
|
// Stylesheets aren't directly testable
|
|
24568
24568
|
/* c8 ignore next */
|
|
24569
|
-
const styles$
|
|
24569
|
+
const styles$r = StyleSheet.create({
|
|
24570
24570
|
mobileTable: {
|
|
24571
24571
|
[mediaQueries.smOrSmaller]: {
|
|
24572
24572
|
minWidth: "auto"
|
|
@@ -24802,7 +24802,7 @@ class CSProgram extends React.Component {
|
|
|
24802
24802
|
// creator "went wild".
|
|
24803
24803
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
24804
24804
|
return /*#__PURE__*/React.createElement("div", {
|
|
24805
|
-
className: css(styles$
|
|
24805
|
+
className: css(styles$q.widthOverride, styleContainer && styles$q.container)
|
|
24806
24806
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
24807
24807
|
sandbox: sandboxOptions,
|
|
24808
24808
|
src: url,
|
|
@@ -24831,7 +24831,7 @@ CSProgram.defaultProps = {
|
|
|
24831
24831
|
// optional message
|
|
24832
24832
|
message: null
|
|
24833
24833
|
};
|
|
24834
|
-
const styles$
|
|
24834
|
+
const styles$q = StyleSheet.create({
|
|
24835
24835
|
// Override the inherited width from the perseus paragraph class
|
|
24836
24836
|
// 820 is minimum width for 420px editor and 400px canvas
|
|
24837
24837
|
widthOverride: {
|
|
@@ -24874,7 +24874,7 @@ class Definition extends React.Component {
|
|
|
24874
24874
|
}) => /*#__PURE__*/React.createElement(Popover, {
|
|
24875
24875
|
content: /*#__PURE__*/React.createElement(PopoverContentCore, {
|
|
24876
24876
|
color: "white",
|
|
24877
|
-
style: styles$
|
|
24877
|
+
style: styles$p.tooltipBody,
|
|
24878
24878
|
closeButtonVisible: true
|
|
24879
24879
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
24880
24880
|
apiOptions: this.props.apiOptions,
|
|
@@ -24907,7 +24907,7 @@ Definition.defaultProps = {
|
|
|
24907
24907
|
togglePrompt: "define me",
|
|
24908
24908
|
definition: "definition goes here"
|
|
24909
24909
|
};
|
|
24910
|
-
const styles$
|
|
24910
|
+
const styles$p = {
|
|
24911
24911
|
tooltipBody: {
|
|
24912
24912
|
color: color.offBlack,
|
|
24913
24913
|
fontSize: 20,
|
|
@@ -25135,7 +25135,7 @@ class Explanation extends React.Component {
|
|
|
25135
25135
|
marginRight: "-6px",
|
|
25136
25136
|
"white-space": "normal"
|
|
25137
25137
|
};
|
|
25138
|
-
const contentStyling = [styles$
|
|
25138
|
+
const contentStyling = [styles$o.content, this.state.expanded ? styles$o.contentExpanded : styles$o.contentCollapsed, allowTransition && (this.state.expanded ? styles$o.transitionExpanded : styles$o.transitionCollapsed)];
|
|
25139
25139
|
return /*#__PURE__*/React.createElement(UniqueIDProvider, {
|
|
25140
25140
|
mockOnFirstRender: true,
|
|
25141
25141
|
scope: "explanation-widget"
|
|
@@ -25154,7 +25154,7 @@ class Explanation extends React.Component {
|
|
|
25154
25154
|
"aria-hidden": !this.state.expanded,
|
|
25155
25155
|
testId: "content-container"
|
|
25156
25156
|
}, /*#__PURE__*/React.createElement(View, {
|
|
25157
|
-
style: styles$
|
|
25157
|
+
style: styles$o.contentWrapper
|
|
25158
25158
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
25159
25159
|
apiOptions: this.props.apiOptions,
|
|
25160
25160
|
content: this.props.explanation,
|
|
@@ -25175,7 +25175,7 @@ Explanation.defaultProps = {
|
|
|
25175
25175
|
const leftBorderSpacing = 23;
|
|
25176
25176
|
const verticalContentPadding = 10;
|
|
25177
25177
|
const arrowHeight = 14;
|
|
25178
|
-
const styles$
|
|
25178
|
+
const styles$o = StyleSheet.create({
|
|
25179
25179
|
content: {
|
|
25180
25180
|
borderLeft: "0px solid #ccc",
|
|
25181
25181
|
display: "inline-grid",
|
|
@@ -25239,15 +25239,15 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
25239
25239
|
correctExcited,
|
|
25240
25240
|
nextQuestion
|
|
25241
25241
|
} = this.context.strings;
|
|
25242
|
-
const answerBarStyle = _extends({}, styles$
|
|
25242
|
+
const answerBarStyle = _extends({}, styles$n.answerBar, {
|
|
25243
25243
|
backgroundColor: answerBarState === "CORRECT" ? color.offWhite : "white",
|
|
25244
25244
|
// Center the "Correct!" message only when there's no next question
|
|
25245
25245
|
justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
|
|
25246
25246
|
});
|
|
25247
25247
|
const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React.createElement("span", {
|
|
25248
|
-
style: styles$
|
|
25248
|
+
style: styles$n.text
|
|
25249
25249
|
}, /*#__PURE__*/React.createElement("span", {
|
|
25250
|
-
style: styles$
|
|
25250
|
+
style: styles$n.tryAgainIcon
|
|
25251
25251
|
}, /*#__PURE__*/React.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React.createElement("span", {
|
|
25252
25252
|
style: {
|
|
25253
25253
|
marginLeft: 8
|
|
@@ -25266,7 +25266,7 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
25266
25266
|
return /*#__PURE__*/React.createElement("div", {
|
|
25267
25267
|
style: answerBarStyle
|
|
25268
25268
|
}, /*#__PURE__*/React.createElement("span", {
|
|
25269
|
-
style: styles$
|
|
25269
|
+
style: styles$n.text
|
|
25270
25270
|
}, /*#__PURE__*/React.createElement("span", {
|
|
25271
25271
|
style: {
|
|
25272
25272
|
fontSize: 28,
|
|
@@ -25289,7 +25289,7 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
25289
25289
|
}
|
|
25290
25290
|
GradedGroupAnswerBar.contextType = PerseusI18nContext;
|
|
25291
25291
|
const fontSize = 17;
|
|
25292
|
-
const styles$
|
|
25292
|
+
const styles$n = {
|
|
25293
25293
|
answerBar: {
|
|
25294
25294
|
display: "flex",
|
|
25295
25295
|
alignItems: "center",
|
|
@@ -25474,7 +25474,7 @@ class GradedGroup extends React.Component {
|
|
|
25474
25474
|
}));
|
|
25475
25475
|
gradeStatus = this.context.strings.incorrect;
|
|
25476
25476
|
}
|
|
25477
|
-
const mobileClass = this.props.inGradedGroupSet ? css(styles$
|
|
25477
|
+
const mobileClass = this.props.inGradedGroupSet ? css(styles$m.gradedGroupInSet) : css(styles$m.gradedGroup);
|
|
25478
25478
|
const classes = classNames({
|
|
25479
25479
|
[mobileClass]: apiOptions.isMobile,
|
|
25480
25480
|
"perseus-graded-group": true,
|
|
@@ -25493,7 +25493,7 @@ class GradedGroup extends React.Component {
|
|
|
25493
25493
|
return /*#__PURE__*/React.createElement("div", {
|
|
25494
25494
|
className: classes
|
|
25495
25495
|
}, !!this.props.title && /*#__PURE__*/React.createElement("div", {
|
|
25496
|
-
className: css(styles$
|
|
25496
|
+
className: css(styles$m.title)
|
|
25497
25497
|
}, this.props.title), /*#__PURE__*/React.createElement(Renderer, _extends({}, this.props, {
|
|
25498
25498
|
// eslint-disable-next-line react/no-string-refs
|
|
25499
25499
|
ref: "renderer",
|
|
@@ -25526,7 +25526,7 @@ class GradedGroup extends React.Component {
|
|
|
25526
25526
|
}, this.context.strings.nextQuestion), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
|
|
25527
25527
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
25528
25528
|
tabIndex: "0",
|
|
25529
|
-
className: css(styles$
|
|
25529
|
+
className: css(styles$m.explanationTitle),
|
|
25530
25530
|
onClick: () => this.setState({
|
|
25531
25531
|
showHint: false
|
|
25532
25532
|
}),
|
|
@@ -25559,7 +25559,7 @@ class GradedGroup extends React.Component {
|
|
|
25559
25559
|
showHint: true
|
|
25560
25560
|
});
|
|
25561
25561
|
},
|
|
25562
|
-
className: css(styles$
|
|
25562
|
+
className: css(styles$m.showHintLink)
|
|
25563
25563
|
}, this.context.strings.explain)), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React.createElement(GradedGroupAnswerBar, {
|
|
25564
25564
|
apiOptions: apiOptions,
|
|
25565
25565
|
answerBarState: answerBarState,
|
|
@@ -25581,7 +25581,7 @@ GradedGroup.defaultProps = {
|
|
|
25581
25581
|
const traverseChildWidgets$2 = function traverseChildWidgets(props, traverseRenderer) {
|
|
25582
25582
|
return _.extend({}, props, traverseRenderer(props));
|
|
25583
25583
|
};
|
|
25584
|
-
const styles$
|
|
25584
|
+
const styles$m = StyleSheet.create({
|
|
25585
25585
|
gradedGroupInSet: {
|
|
25586
25586
|
// Reset a few desktop-only styles that come from graded-group.less
|
|
25587
25587
|
marginLeft: 0,
|
|
@@ -25654,18 +25654,18 @@ class Indicators extends React.Component {
|
|
|
25654
25654
|
return /*#__PURE__*/React.createElement("ul", {
|
|
25655
25655
|
// reduntantly add class name for use in .less files--
|
|
25656
25656
|
// the styles object key gets hashed
|
|
25657
|
-
className: classNames(css(styles$
|
|
25657
|
+
className: classNames(css(styles$l.indicatorContainer), "indicatorContainer")
|
|
25658
25658
|
}, this.props.gradedGroups.map(({
|
|
25659
25659
|
title
|
|
25660
25660
|
}, i) => /*#__PURE__*/React.createElement("li", {
|
|
25661
|
-
className: css(styles$
|
|
25661
|
+
className: css(styles$l.indicator),
|
|
25662
25662
|
key: title
|
|
25663
25663
|
}, /*#__PURE__*/React.createElement(Clickable, {
|
|
25664
25664
|
role: "button",
|
|
25665
25665
|
"aria-label": this.context.strings.skipToTitle({
|
|
25666
25666
|
title
|
|
25667
25667
|
}),
|
|
25668
|
-
style: styles$
|
|
25668
|
+
style: styles$l.indicatorButton,
|
|
25669
25669
|
onClick: () => this.props.onChangeCurrentGroup(i),
|
|
25670
25670
|
onKeyDown: e => this.handleKeyDown(e, i)
|
|
25671
25671
|
}, ({
|
|
@@ -25673,9 +25673,9 @@ class Indicators extends React.Component {
|
|
|
25673
25673
|
focused,
|
|
25674
25674
|
pressed
|
|
25675
25675
|
}) => /*#__PURE__*/React.createElement(View, {
|
|
25676
|
-
style: [styles$
|
|
25676
|
+
style: [styles$l.indicatorDot, (hovered || focused || pressed) && styles$l.indicatorDotFocused]
|
|
25677
25677
|
}, i === this.props.currentGroup && /*#__PURE__*/React.createElement(View, {
|
|
25678
|
-
style: styles$
|
|
25678
|
+
style: styles$l.indicatorDotActive
|
|
25679
25679
|
}, /*#__PURE__*/React.createElement("span", {
|
|
25680
25680
|
className: css(a11y.srOnly)
|
|
25681
25681
|
}, this.context.strings.current)))))));
|
|
@@ -25739,7 +25739,7 @@ class GradedGroupSet extends React.Component {
|
|
|
25739
25739
|
} = getDependencies();
|
|
25740
25740
|
if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
|
|
25741
25741
|
return /*#__PURE__*/React.createElement("div", {
|
|
25742
|
-
className: css(styles$
|
|
25742
|
+
className: css(styles$l.container)
|
|
25743
25743
|
}, this.props.gradedGroups.map((gradedGroup, i) => {
|
|
25744
25744
|
return (
|
|
25745
25745
|
/*#__PURE__*/
|
|
@@ -25762,13 +25762,13 @@ class GradedGroupSet extends React.Component {
|
|
|
25762
25762
|
const numGroups = this.props.gradedGroups.length;
|
|
25763
25763
|
const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
|
|
25764
25764
|
return /*#__PURE__*/React.createElement("div", {
|
|
25765
|
-
className: css(styles$
|
|
25765
|
+
className: css(styles$l.container)
|
|
25766
25766
|
}, /*#__PURE__*/React.createElement("div", {
|
|
25767
|
-
className: css(styles$
|
|
25767
|
+
className: css(styles$l.top)
|
|
25768
25768
|
}, /*#__PURE__*/React.createElement("div", {
|
|
25769
|
-
className: css(styles$
|
|
25769
|
+
className: css(styles$l.title)
|
|
25770
25770
|
}, currentGroup.title), /*#__PURE__*/React.createElement("div", {
|
|
25771
|
-
className: css(styles$
|
|
25771
|
+
className: css(styles$l.spacer)
|
|
25772
25772
|
}), /*#__PURE__*/React.createElement(Indicators, {
|
|
25773
25773
|
currentGroup: this.state.currentGroup,
|
|
25774
25774
|
gradedGroups: this.props.gradedGroups,
|
|
@@ -25810,7 +25810,7 @@ var GradedGroupSet$1 = {
|
|
|
25810
25810
|
tracking: "all",
|
|
25811
25811
|
isLintable: true
|
|
25812
25812
|
};
|
|
25813
|
-
const styles$
|
|
25813
|
+
const styles$l = StyleSheet.create({
|
|
25814
25814
|
top: {
|
|
25815
25815
|
display: "flex",
|
|
25816
25816
|
flexDirection: "row"
|
|
@@ -25915,7 +25915,7 @@ class ButtonGroup extends React.Component {
|
|
|
25915
25915
|
id: "" + i,
|
|
25916
25916
|
ref: "button" + i,
|
|
25917
25917
|
key: "" + i,
|
|
25918
|
-
className: css(styles$
|
|
25918
|
+
className: css(styles$k.buttonStyle, button.value === value && styles$k.selectedStyle),
|
|
25919
25919
|
onClick: () => this.toggleSelect(button.value)
|
|
25920
25920
|
}, button.content || "" + button.value);
|
|
25921
25921
|
});
|
|
@@ -25932,7 +25932,7 @@ ButtonGroup.defaultProps = {
|
|
|
25932
25932
|
value: null,
|
|
25933
25933
|
allowEmpty: true
|
|
25934
25934
|
};
|
|
25935
|
-
const styles$
|
|
25935
|
+
const styles$k = StyleSheet.create({
|
|
25936
25936
|
buttonStyle: {
|
|
25937
25937
|
backgroundColor: "white",
|
|
25938
25938
|
border: "1px solid #ccc",
|
|
@@ -26536,7 +26536,7 @@ var util = /*#__PURE__*/Object.freeze({
|
|
|
26536
26536
|
});
|
|
26537
26537
|
|
|
26538
26538
|
// @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
|
|
26539
|
-
const MovablePoint$
|
|
26539
|
+
const MovablePoint$3 = Graphie.MovablePoint;
|
|
26540
26540
|
// @ts-expect-error - TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
26541
26541
|
const MovableLine$2 = Graphie.MovableLine;
|
|
26542
26542
|
function isFlipped(newCoord, oldCoord, line) {
|
|
@@ -26618,7 +26618,7 @@ class FunctionGrapher extends React.Component {
|
|
|
26618
26618
|
}],
|
|
26619
26619
|
normalStyle: dashed,
|
|
26620
26620
|
highlightStyle: dashed
|
|
26621
|
-
}, _.map(asymptote, (coord, i) => /*#__PURE__*/React.createElement(MovablePoint$
|
|
26621
|
+
}, _.map(asymptote, (coord, i) => /*#__PURE__*/React.createElement(MovablePoint$3, {
|
|
26622
26622
|
key: `asymptoteCoord-${i}`,
|
|
26623
26623
|
coord: coord,
|
|
26624
26624
|
static: true,
|
|
@@ -26633,7 +26633,7 @@ class FunctionGrapher extends React.Component {
|
|
|
26633
26633
|
}
|
|
26634
26634
|
render() {
|
|
26635
26635
|
const pointForCoord = (coord, i) => {
|
|
26636
|
-
return /*#__PURE__*/React.createElement(MovablePoint$
|
|
26636
|
+
return /*#__PURE__*/React.createElement(MovablePoint$3, {
|
|
26637
26637
|
key: i,
|
|
26638
26638
|
coord: coord,
|
|
26639
26639
|
static: this.props.static,
|
|
@@ -27442,7 +27442,7 @@ const Label = Graphie.Label;
|
|
|
27442
27442
|
// @ts-expect-error - TS2339 - Property 'Line' does not exist on type 'typeof Graphie'.
|
|
27443
27443
|
const Line$2 = Graphie.Line;
|
|
27444
27444
|
// @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
|
|
27445
|
-
const MovablePoint$
|
|
27445
|
+
const MovablePoint$2 = Graphie.MovablePoint;
|
|
27446
27446
|
// @ts-expect-error - TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
27447
27447
|
const MovableLine$1 = Graphie.MovableLine;
|
|
27448
27448
|
// @ts-expect-error - TS2339 - Property 'Plot' does not exist on type 'typeof Graphie'.
|
|
@@ -27691,7 +27691,7 @@ class Interaction extends React.Component {
|
|
|
27691
27691
|
return [coordX, coordY];
|
|
27692
27692
|
}];
|
|
27693
27693
|
if (element.options.constraint === "snap") {
|
|
27694
|
-
constraints.push(MovablePoint$
|
|
27694
|
+
constraints.push(MovablePoint$2.constraints.snap(element.options.snap));
|
|
27695
27695
|
} else if (element.options.constraint === "x") {
|
|
27696
27696
|
constraints.push(coord => {
|
|
27697
27697
|
return [
|
|
@@ -27713,7 +27713,7 @@ class Interaction extends React.Component {
|
|
|
27713
27713
|
// TODO(eater): foo_[xyz] are hacky non-props to
|
|
27714
27714
|
// get the component to update when constraints
|
|
27715
27715
|
// change
|
|
27716
|
-
return /*#__PURE__*/React.createElement(MovablePoint$
|
|
27716
|
+
return /*#__PURE__*/React.createElement(MovablePoint$2, {
|
|
27717
27717
|
key: element.key,
|
|
27718
27718
|
coord: [
|
|
27719
27719
|
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
@@ -27748,7 +27748,7 @@ class Interaction extends React.Component {
|
|
|
27748
27748
|
return [coordX, coordY];
|
|
27749
27749
|
}];
|
|
27750
27750
|
if (element.options.constraint === "snap") {
|
|
27751
|
-
constraints.push(MovablePoint$
|
|
27751
|
+
constraints.push(MovablePoint$2.constraints.snap(element.options.snap));
|
|
27752
27752
|
} else if (element.options.constraint === "x") {
|
|
27753
27753
|
constraints.push(coord => {
|
|
27754
27754
|
return [
|
|
@@ -27789,14 +27789,14 @@ class Interaction extends React.Component {
|
|
|
27789
27789
|
foo_x: element.options.constraint,
|
|
27790
27790
|
foo_y: element.options.constraintFn,
|
|
27791
27791
|
foo_z: element.options.snap
|
|
27792
|
-
}, /*#__PURE__*/React.createElement(MovablePoint$
|
|
27792
|
+
}, /*#__PURE__*/React.createElement(MovablePoint$2, {
|
|
27793
27793
|
coord: start,
|
|
27794
27794
|
static: true,
|
|
27795
27795
|
normalStyle: {
|
|
27796
27796
|
stroke: "none",
|
|
27797
27797
|
fill: "none"
|
|
27798
27798
|
}
|
|
27799
|
-
}), /*#__PURE__*/React.createElement(MovablePoint$
|
|
27799
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$2, {
|
|
27800
27800
|
coord: end,
|
|
27801
27801
|
static: true,
|
|
27802
27802
|
normalStyle: {
|
|
@@ -28353,7 +28353,7 @@ const defaultGraphConfig = {
|
|
|
28353
28353
|
width: 0,
|
|
28354
28354
|
height: 0,
|
|
28355
28355
|
labels: [],
|
|
28356
|
-
|
|
28356
|
+
disableKeyboardInteraction: false
|
|
28357
28357
|
};
|
|
28358
28358
|
const GraphConfigContext = /*#__PURE__*/createContext(defaultGraphConfig);
|
|
28359
28359
|
function useGraphConfig() {
|
|
@@ -28490,6 +28490,28 @@ const segmentsIntersect = ([[a, b], [c, d]], [[p, q], [r, s]]) => {
|
|
|
28490
28490
|
}
|
|
28491
28491
|
};
|
|
28492
28492
|
|
|
28493
|
+
// Finds the unique intersection point between two rays. Returns undefined if
|
|
28494
|
+
// there is not exactly one intersection point. The first point in each of the
|
|
28495
|
+
// given ray "segments" should be the initial point of the ray. The second point
|
|
28496
|
+
// can be any arbitrary point on the ray different from the initial point.
|
|
28497
|
+
function findIntersectionOfRays([[a, b], [c, d]], [[p, q], [r, s]]) {
|
|
28498
|
+
// See https://stackoverflow.com/a/24392281/7347484 for an explanation of
|
|
28499
|
+
// the determinant and lambda values.
|
|
28500
|
+
const determinant = (c - a) * (s - q) - (r - p) * (d - b);
|
|
28501
|
+
if (determinant === 0) {
|
|
28502
|
+
return undefined;
|
|
28503
|
+
} else {
|
|
28504
|
+
const lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / determinant;
|
|
28505
|
+
const gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / determinant;
|
|
28506
|
+
if (lambda <= 0 || gamma >= 1) {
|
|
28507
|
+
return undefined;
|
|
28508
|
+
}
|
|
28509
|
+
const initialPoint = [a, b];
|
|
28510
|
+
const direction = vec.sub([c, d], initialPoint);
|
|
28511
|
+
return vec.add(initialPoint, vec.scale(direction, lambda));
|
|
28512
|
+
}
|
|
28513
|
+
}
|
|
28514
|
+
|
|
28493
28515
|
// This file contains helper functions for working with angles.
|
|
28494
28516
|
|
|
28495
28517
|
function convertDegreesToRadians(degrees) {
|
|
@@ -28501,6 +28523,8 @@ function convertDegreesToRadians(degrees) {
|
|
|
28501
28523
|
function calculateAngleInDegrees([x, y]) {
|
|
28502
28524
|
return Math.atan2(y, x) * 180 / Math.PI;
|
|
28503
28525
|
}
|
|
28526
|
+
|
|
28527
|
+
// Converts polar coordinates to cartesian. The th(eta) parameter is in degrees.
|
|
28504
28528
|
function polar(r, th) {
|
|
28505
28529
|
if (typeof r === "number") {
|
|
28506
28530
|
r = [r, r];
|
|
@@ -29106,7 +29130,7 @@ const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
|
29106
29130
|
width: "24",
|
|
29107
29131
|
height: "24",
|
|
29108
29132
|
viewBox: "0 0 24 24",
|
|
29109
|
-
className: css(styles$
|
|
29133
|
+
className: css(styles$j.icon)
|
|
29110
29134
|
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
29111
29135
|
id: "a",
|
|
29112
29136
|
d: "M7.401 10.035c-1.424.748-2.599 1.905-3.544 " + "3.48a1 1 0 0 1-1.714-1.03C4.325 8.849 7.652 7 " + "12 7c4.348 0 7.675 1.848 9.857 5.486a1 1 0 0 " + "1-1.714 1.028c-.945-1.574-2.12-2.73-3.544-" + "3.48a5 5 0 1 1-9.198 0zM12 15a3 3 0 1 0 0-6 3 3 " + "0 0 0 0 6z"
|
|
@@ -29137,7 +29161,7 @@ const HiddenIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
|
29137
29161
|
width: "24",
|
|
29138
29162
|
height: "24",
|
|
29139
29163
|
viewBox: "0 0 24 24",
|
|
29140
|
-
className: css(styles$
|
|
29164
|
+
className: css(styles$j.icon)
|
|
29141
29165
|
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
29142
29166
|
id: "a",
|
|
29143
29167
|
d: "M8.794 7.38C9.791 7.127 10.86 7 12 7c4.348 0 " + "7.675 1.848 9.857 5.486a1 1 0 0 1-1.714 " + "1.028c-.945-1.574-2.12-2.73-3.544-3.48.258." + "604.401 1.268.401 1.966 0 1.02-.305 " + "1.967-.828 2.757l2.535 2.536a1 1 0 0 " + "1-1.414 1.414l-12-12a1 1 0 0 1 " + "1.414-1.414L8.794 7.38zm5.914 5.913a3 3 0 0 " + "0-4.001-4.001l4 4.001zM6.072 8.486l2.976 " + "2.976a3 3 0 0 0 3.49 3.49l1.579 1.58A5 5 0 " + "0 1 7.4 10.035c-1.424.747-2.599 1.904-3.544 " + "3.478a1 1 0 0 1-1.714-1.028c1.049-1.75 " + "2.363-3.085 3.929-4z"
|
|
@@ -29171,20 +29195,20 @@ const HUD = ({
|
|
|
29171
29195
|
let state;
|
|
29172
29196
|
let icon;
|
|
29173
29197
|
if (enabled) {
|
|
29174
|
-
state = styles$
|
|
29198
|
+
state = styles$j.enabled;
|
|
29175
29199
|
icon = /*#__PURE__*/React.createElement(VisibleIcon, null);
|
|
29176
29200
|
} else {
|
|
29177
|
-
state = styles$
|
|
29201
|
+
state = styles$j.disabled;
|
|
29178
29202
|
icon = /*#__PURE__*/React.createElement(HiddenIcon, null);
|
|
29179
29203
|
}
|
|
29180
29204
|
return /*#__PURE__*/React.createElement("button", {
|
|
29181
|
-
className: css(styles$
|
|
29205
|
+
className: css(styles$j.hud, _fixedPosition && styles$j.hudFixedPosition, state),
|
|
29182
29206
|
onClick: e => {
|
|
29183
29207
|
onClick();
|
|
29184
29208
|
}
|
|
29185
29209
|
}, icon, message);
|
|
29186
29210
|
};
|
|
29187
|
-
const styles$
|
|
29211
|
+
const styles$j = StyleSheet.create({
|
|
29188
29212
|
hud: {
|
|
29189
29213
|
boxSizing: "border-box",
|
|
29190
29214
|
height: 36,
|
|
@@ -29234,19 +29258,19 @@ const styles$k = StyleSheet.create({
|
|
|
29234
29258
|
}
|
|
29235
29259
|
});
|
|
29236
29260
|
|
|
29237
|
-
const
|
|
29261
|
+
const InfoTipBase = props => {
|
|
29238
29262
|
return /*#__PURE__*/React.createElement(Tooltip$1, {
|
|
29239
29263
|
content: /*#__PURE__*/React.createElement(Body, {
|
|
29240
|
-
style: styles$
|
|
29264
|
+
style: styles$i.body
|
|
29241
29265
|
}, props.children),
|
|
29242
29266
|
placement: "right"
|
|
29243
29267
|
}, /*#__PURE__*/React.createElement(PhosphorIcon, {
|
|
29244
29268
|
size: "small",
|
|
29245
29269
|
icon: questionIcon,
|
|
29246
|
-
style: styles$
|
|
29270
|
+
style: styles$i.spacingLeft
|
|
29247
29271
|
}));
|
|
29248
29272
|
};
|
|
29249
|
-
const styles$
|
|
29273
|
+
const styles$i = StyleSheet.create({
|
|
29250
29274
|
spacingLeft: {
|
|
29251
29275
|
marginInlineStart: spacing.xxxSmall_4
|
|
29252
29276
|
},
|
|
@@ -29278,7 +29302,7 @@ class InfoTip extends React.Component {
|
|
|
29278
29302
|
|
|
29279
29303
|
render() {
|
|
29280
29304
|
if (this.state.didMount) {
|
|
29281
|
-
return /*#__PURE__*/React.createElement(
|
|
29305
|
+
return /*#__PURE__*/React.createElement(InfoTipBase, this.props);
|
|
29282
29306
|
}
|
|
29283
29307
|
return /*#__PURE__*/React.createElement("div", null);
|
|
29284
29308
|
}
|
|
@@ -29325,7 +29349,7 @@ class MultiButtonGroup extends React.Component {
|
|
|
29325
29349
|
id: "" + i,
|
|
29326
29350
|
key: "" + i,
|
|
29327
29351
|
ref: "button" + i,
|
|
29328
|
-
className: css(styles$
|
|
29352
|
+
className: css(styles$h.buttonStyle, selected && styles$h.selectedStyle),
|
|
29329
29353
|
onClick: () => this.toggleSelect(button.value)
|
|
29330
29354
|
}, button.content || "" + button.value);
|
|
29331
29355
|
});
|
|
@@ -29341,7 +29365,7 @@ MultiButtonGroup.defaultProps = {
|
|
|
29341
29365
|
values: [],
|
|
29342
29366
|
allowEmpty: true
|
|
29343
29367
|
};
|
|
29344
|
-
const styles$
|
|
29368
|
+
const styles$h = StyleSheet.create({
|
|
29345
29369
|
buttonStyle: {
|
|
29346
29370
|
backgroundColor: "white",
|
|
29347
29371
|
border: "1px solid #ccc",
|
|
@@ -29566,62 +29590,6 @@ NumberInput.defaultProps = {
|
|
|
29566
29590
|
useArrowKeys: false
|
|
29567
29591
|
};
|
|
29568
29592
|
|
|
29569
|
-
/* eslint-disable @babel/no-invalid-this */
|
|
29570
|
-
|
|
29571
|
-
/* A checkbox that syncs its value to props using the
|
|
29572
|
-
* renderer's onChange method, and gets the prop name
|
|
29573
|
-
* dynamically from its props list
|
|
29574
|
-
*/
|
|
29575
|
-
const PropCheckBox = createReactClass({
|
|
29576
|
-
displayName: "PropCheckBox",
|
|
29577
|
-
propTypes: {
|
|
29578
|
-
labelAlignment: PropTypes.oneOf(["left", "right"])
|
|
29579
|
-
},
|
|
29580
|
-
DEFAULT_PROPS: {
|
|
29581
|
-
label: null,
|
|
29582
|
-
onChange: null,
|
|
29583
|
-
labelAlignment: "left"
|
|
29584
|
-
},
|
|
29585
|
-
getDefaultProps: function () {
|
|
29586
|
-
return this.DEFAULT_PROPS;
|
|
29587
|
-
},
|
|
29588
|
-
propName: function () {
|
|
29589
|
-
const propName = _.find(_.keys(this.props), function (localPropName) {
|
|
29590
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
29591
|
-
return !_.has(this.DEFAULT_PROPS, localPropName);
|
|
29592
|
-
}, this);
|
|
29593
|
-
if (!propName) {
|
|
29594
|
-
throw new PerseusError("Attempted to create a PropCheckBox with no prop!", Errors.InvalidInput);
|
|
29595
|
-
}
|
|
29596
|
-
return propName;
|
|
29597
|
-
},
|
|
29598
|
-
_labelAlignLeft: function () {
|
|
29599
|
-
return this.props.labelAlignment === "left";
|
|
29600
|
-
},
|
|
29601
|
-
render: function () {
|
|
29602
|
-
const propName = this.propName();
|
|
29603
|
-
return /*#__PURE__*/React.createElement("label", {
|
|
29604
|
-
className: css(styles$h.labeledCheckbox)
|
|
29605
|
-
}, this._labelAlignLeft() && /*#__PURE__*/React.createElement(LabelSmall, null, this.props.label), /*#__PURE__*/React.createElement(Checkbox, {
|
|
29606
|
-
checked: this.props[propName],
|
|
29607
|
-
onChange: this.toggle
|
|
29608
|
-
}), !this._labelAlignLeft() && /*#__PURE__*/React.createElement(LabelSmall, null, this.props.label));
|
|
29609
|
-
},
|
|
29610
|
-
toggle: function () {
|
|
29611
|
-
const propName = this.propName();
|
|
29612
|
-
const changes = {};
|
|
29613
|
-
changes[propName] = !this.props[propName];
|
|
29614
|
-
this.props.onChange(changes);
|
|
29615
|
-
}
|
|
29616
|
-
});
|
|
29617
|
-
const styles$h = StyleSheet.create({
|
|
29618
|
-
labeledCheckbox: {
|
|
29619
|
-
display: "flex",
|
|
29620
|
-
flexDirection: "row",
|
|
29621
|
-
alignItems: "center"
|
|
29622
|
-
}
|
|
29623
|
-
});
|
|
29624
|
-
|
|
29625
29593
|
const truth = () => true;
|
|
29626
29594
|
|
|
29627
29595
|
/* A minor abstraction on top of NumberInput for ranges
|
|
@@ -29683,7 +29651,6 @@ var components = /*#__PURE__*/Object.freeze({
|
|
|
29683
29651
|
MathInput: MathInput,
|
|
29684
29652
|
MultiButtonGroup: MultiButtonGroup,
|
|
29685
29653
|
NumberInput: NumberInput,
|
|
29686
|
-
PropCheckBox: PropCheckBox,
|
|
29687
29654
|
RangeInput: RangeInput,
|
|
29688
29655
|
SvgImage: SvgImage,
|
|
29689
29656
|
TextInput: TextInput,
|
|
@@ -29837,8 +29804,9 @@ const lockedFigureColors = {
|
|
|
29837
29804
|
};
|
|
29838
29805
|
const lockedFigureFillStyles = {
|
|
29839
29806
|
none: 0,
|
|
29840
|
-
|
|
29841
|
-
translucent: 0.4
|
|
29807
|
+
white: 1,
|
|
29808
|
+
translucent: 0.4,
|
|
29809
|
+
solid: 1
|
|
29842
29810
|
};
|
|
29843
29811
|
const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
|
|
29844
29812
|
|
|
@@ -29847,7 +29815,7 @@ const LockedEllipse = props => {
|
|
|
29847
29815
|
center,
|
|
29848
29816
|
radius,
|
|
29849
29817
|
angle,
|
|
29850
|
-
color,
|
|
29818
|
+
color: color$1,
|
|
29851
29819
|
fillStyle,
|
|
29852
29820
|
strokeStyle
|
|
29853
29821
|
} = props;
|
|
@@ -29857,11 +29825,21 @@ const LockedEllipse = props => {
|
|
|
29857
29825
|
angle: angle,
|
|
29858
29826
|
fillOpacity: lockedFigureFillStyles[fillStyle],
|
|
29859
29827
|
strokeStyle: strokeStyle,
|
|
29860
|
-
color: lockedFigureColors[color]
|
|
29828
|
+
color: lockedFigureColors[color$1]
|
|
29829
|
+
// We need to override the svg props if we want to have a
|
|
29830
|
+
// different fill color than the stroke color (specifically,
|
|
29831
|
+
// in the case where the fillStyle is "white").
|
|
29832
|
+
,
|
|
29833
|
+
svgEllipseProps: {
|
|
29834
|
+
style: {
|
|
29835
|
+
fill: fillStyle === "white" ? color.white : lockedFigureColors[color$1]
|
|
29836
|
+
}
|
|
29837
|
+
}
|
|
29861
29838
|
});
|
|
29862
29839
|
};
|
|
29863
29840
|
|
|
29864
29841
|
const LockedFunction = props => {
|
|
29842
|
+
const [equation, setEquation] = useState();
|
|
29865
29843
|
const {
|
|
29866
29844
|
color,
|
|
29867
29845
|
strokeStyle,
|
|
@@ -29873,7 +29851,14 @@ const LockedFunction = props => {
|
|
|
29873
29851
|
style: strokeStyle,
|
|
29874
29852
|
domain
|
|
29875
29853
|
};
|
|
29876
|
-
|
|
29854
|
+
useEffect(() => {
|
|
29855
|
+
// Parsing the equation in a "useEffect" hook saves about 2ms each frame
|
|
29856
|
+
// when the learner is interacting with the graph (i.e. moving points).
|
|
29857
|
+
setEquation(KAS.parse(props.equation).expr);
|
|
29858
|
+
}, [props.equation]);
|
|
29859
|
+
if (typeof equation === "undefined") {
|
|
29860
|
+
return null;
|
|
29861
|
+
}
|
|
29877
29862
|
return /*#__PURE__*/React.createElement("g", {
|
|
29878
29863
|
className: "locked-function"
|
|
29879
29864
|
}, directionalAxis === "x" && /*#__PURE__*/React.createElement(Plot$3.OfX, _extends({
|
|
@@ -30064,7 +30049,7 @@ const LockedPoint = props => {
|
|
|
30064
30049
|
const LockedPolygon = props => {
|
|
30065
30050
|
const {
|
|
30066
30051
|
points,
|
|
30067
|
-
color,
|
|
30052
|
+
color: color$1,
|
|
30068
30053
|
showVertices,
|
|
30069
30054
|
fillStyle,
|
|
30070
30055
|
strokeStyle
|
|
@@ -30075,12 +30060,21 @@ const LockedPolygon = props => {
|
|
|
30075
30060
|
points: [...points],
|
|
30076
30061
|
fillOpacity: lockedFigureFillStyles[fillStyle],
|
|
30077
30062
|
strokeStyle: strokeStyle,
|
|
30078
|
-
color: lockedFigureColors[color]
|
|
30063
|
+
color: lockedFigureColors[color$1]
|
|
30064
|
+
// We need to override the svg props if we want to have a
|
|
30065
|
+
// different fill color than the stroke color (specifically,
|
|
30066
|
+
// in the case where the fillStyle is "white").
|
|
30067
|
+
,
|
|
30068
|
+
svgPolygonProps: {
|
|
30069
|
+
style: {
|
|
30070
|
+
fill: fillStyle === "white" ? color.white : lockedFigureColors[color$1]
|
|
30071
|
+
}
|
|
30072
|
+
}
|
|
30079
30073
|
}), showVertices && points.map((point, index) => /*#__PURE__*/React.createElement(Point$2, {
|
|
30080
30074
|
key: `locked-polygon-point-${index}`,
|
|
30081
30075
|
x: point[X],
|
|
30082
30076
|
y: point[Y],
|
|
30083
|
-
color: lockedFigureColors[color]
|
|
30077
|
+
color: lockedFigureColors[color$1]
|
|
30084
30078
|
})));
|
|
30085
30079
|
};
|
|
30086
30080
|
|
|
@@ -30321,7 +30315,7 @@ function useDraggable(args) {
|
|
|
30321
30315
|
gestureTarget: target,
|
|
30322
30316
|
onMove,
|
|
30323
30317
|
point,
|
|
30324
|
-
|
|
30318
|
+
constrainKeyboardMovement
|
|
30325
30319
|
} = args;
|
|
30326
30320
|
const [dragging, setDragging] = React.useState(false);
|
|
30327
30321
|
const {
|
|
@@ -30344,6 +30338,7 @@ function useDraggable(args) {
|
|
|
30344
30338
|
event == null || event.stopPropagation();
|
|
30345
30339
|
const isKeyboard = type.includes("key");
|
|
30346
30340
|
if (isKeyboard) {
|
|
30341
|
+
invariant(event instanceof KeyboardEvent);
|
|
30347
30342
|
event == null || event.preventDefault();
|
|
30348
30343
|
|
|
30349
30344
|
// When a key is held down, we see multiple "keydown" events,
|
|
@@ -30355,6 +30350,11 @@ function useDraggable(args) {
|
|
|
30355
30350
|
if (type === "keyup") {
|
|
30356
30351
|
return;
|
|
30357
30352
|
}
|
|
30353
|
+
if (typeof constrainKeyboardMovement === "object") {
|
|
30354
|
+
const destination = constrainKeyboardMovement[directionForKey[event.key]];
|
|
30355
|
+
onMove(destination != null ? destination : point);
|
|
30356
|
+
return;
|
|
30357
|
+
}
|
|
30358
30358
|
const {
|
|
30359
30359
|
direction: yDownDirection,
|
|
30360
30360
|
altKey,
|
|
@@ -30375,7 +30375,7 @@ function useDraggable(args) {
|
|
|
30375
30375
|
for (const dx of tests) {
|
|
30376
30376
|
// Transform the test back into the point's coordinate system
|
|
30377
30377
|
const testMovement = vec.scale(direction, dx);
|
|
30378
|
-
const testPoint =
|
|
30378
|
+
const testPoint = constrainKeyboardMovement(vec.transform(vec.add(vec.transform(point, userTransform), testMovement), inverseTransform));
|
|
30379
30379
|
if (vec.dist(testPoint, point) > min) {
|
|
30380
30380
|
onMove(testPoint);
|
|
30381
30381
|
break;
|
|
@@ -30395,7 +30395,7 @@ function useDraggable(args) {
|
|
|
30395
30395
|
return;
|
|
30396
30396
|
}
|
|
30397
30397
|
const movement = vec.transform(pixelMovement, inverseViewTransform);
|
|
30398
|
-
onMove(
|
|
30398
|
+
onMove(vec.transform(vec.add(pickup.current, movement), inverseTransform));
|
|
30399
30399
|
}
|
|
30400
30400
|
}, {
|
|
30401
30401
|
target,
|
|
@@ -30407,6 +30407,12 @@ function useDraggable(args) {
|
|
|
30407
30407
|
dragging
|
|
30408
30408
|
};
|
|
30409
30409
|
}
|
|
30410
|
+
const directionForKey = {
|
|
30411
|
+
ArrowLeft: "left",
|
|
30412
|
+
ArrowRight: "right",
|
|
30413
|
+
ArrowUp: "up",
|
|
30414
|
+
ArrowDown: "down"
|
|
30415
|
+
};
|
|
30410
30416
|
function getInverseTransform(transform) {
|
|
30411
30417
|
const invert = vec.matrixInvert(transform);
|
|
30412
30418
|
invariant(invert !== null, "Could not invert transform matrix. A parent transformation matrix might be degenerative (mapping 2D space to a line).");
|
|
@@ -30456,7 +30462,7 @@ const MovablePointView = /*#__PURE__*/forwardRef((props, hitboxRef) => {
|
|
|
30456
30462
|
range,
|
|
30457
30463
|
markings,
|
|
30458
30464
|
showTooltips,
|
|
30459
|
-
|
|
30465
|
+
disableKeyboardInteraction
|
|
30460
30466
|
} = useGraphConfig();
|
|
30461
30467
|
const {
|
|
30462
30468
|
point,
|
|
@@ -30498,7 +30504,7 @@ const MovablePointView = /*#__PURE__*/forwardRef((props, hitboxRef) => {
|
|
|
30498
30504
|
cursor
|
|
30499
30505
|
},
|
|
30500
30506
|
"data-testid": "movable-point",
|
|
30501
|
-
tabIndex:
|
|
30507
|
+
tabIndex: disableKeyboardInteraction ? -1 : tabIndex(focusBehavior)
|
|
30502
30508
|
}, /*#__PURE__*/React.createElement("circle", {
|
|
30503
30509
|
className: "movable-point-hitbox",
|
|
30504
30510
|
r: hitboxSizePx / 2,
|
|
@@ -30587,7 +30593,7 @@ const MovableLine = props => {
|
|
|
30587
30593
|
function useControlPoint(point, color, onMovePoint) {
|
|
30588
30594
|
const {
|
|
30589
30595
|
snapStep,
|
|
30590
|
-
|
|
30596
|
+
disableKeyboardInteraction
|
|
30591
30597
|
} = useGraphConfig();
|
|
30592
30598
|
const [focused, setFocused] = useState(false);
|
|
30593
30599
|
const keyboardHandleRef = useRef(null);
|
|
@@ -30595,7 +30601,7 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
30595
30601
|
gestureTarget: keyboardHandleRef,
|
|
30596
30602
|
point,
|
|
30597
30603
|
onMove: onMovePoint,
|
|
30598
|
-
|
|
30604
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30599
30605
|
});
|
|
30600
30606
|
const visiblePointRef = useRef(null);
|
|
30601
30607
|
const {
|
|
@@ -30604,12 +30610,12 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
30604
30610
|
gestureTarget: visiblePointRef,
|
|
30605
30611
|
point,
|
|
30606
30612
|
onMove: onMovePoint,
|
|
30607
|
-
|
|
30613
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30608
30614
|
});
|
|
30609
30615
|
const focusableHandle = /*#__PURE__*/React.createElement("g", {
|
|
30610
30616
|
"data-testid": "movable-point__focusable-handle",
|
|
30611
30617
|
className: "movable-point__focusable-handle",
|
|
30612
|
-
tabIndex:
|
|
30618
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
30613
30619
|
ref: keyboardHandleRef,
|
|
30614
30620
|
onFocus: () => setFocused(true),
|
|
30615
30621
|
onBlur: () => setFocused(false)
|
|
@@ -30643,7 +30649,7 @@ const Line$1 = props => {
|
|
|
30643
30649
|
range,
|
|
30644
30650
|
graphDimensionsInPixels,
|
|
30645
30651
|
snapStep,
|
|
30646
|
-
|
|
30652
|
+
disableKeyboardInteraction
|
|
30647
30653
|
} = useGraphConfig();
|
|
30648
30654
|
let startExtend = undefined;
|
|
30649
30655
|
let endExtend = undefined;
|
|
@@ -30661,11 +30667,11 @@ const Line$1 = props => {
|
|
|
30661
30667
|
onMove: newPoint => {
|
|
30662
30668
|
onMove(vec.sub(newPoint, start));
|
|
30663
30669
|
},
|
|
30664
|
-
|
|
30670
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30665
30671
|
});
|
|
30666
30672
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("g", {
|
|
30667
30673
|
ref: line,
|
|
30668
|
-
tabIndex:
|
|
30674
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
30669
30675
|
className: "movable-line",
|
|
30670
30676
|
"data-testid": "movable-line",
|
|
30671
30677
|
style: {
|
|
@@ -31128,7 +31134,7 @@ function calculateBisectorPoint(point1, point2, vertex, isReflex, allowReflex, a
|
|
|
31128
31134
|
return scaledBisector;
|
|
31129
31135
|
}
|
|
31130
31136
|
|
|
31131
|
-
const
|
|
31137
|
+
const MovablePoint$1 = props => {
|
|
31132
31138
|
const {
|
|
31133
31139
|
snapStep
|
|
31134
31140
|
} = useGraphConfig();
|
|
@@ -31138,16 +31144,15 @@ const StyledMovablePoint = props => {
|
|
|
31138
31144
|
onMove,
|
|
31139
31145
|
cursor,
|
|
31140
31146
|
color: color$1 = color.blue,
|
|
31141
|
-
|
|
31147
|
+
constrain = p => snap(snapStep, p)
|
|
31142
31148
|
} = props;
|
|
31143
|
-
const snapToValue = snapTo != null ? snapTo : "grid";
|
|
31144
31149
|
const {
|
|
31145
31150
|
dragging
|
|
31146
31151
|
} = useDraggable({
|
|
31147
31152
|
gestureTarget: elementRef,
|
|
31148
31153
|
point,
|
|
31149
31154
|
onMove,
|
|
31150
|
-
|
|
31155
|
+
constrainKeyboardMovement: constrain
|
|
31151
31156
|
});
|
|
31152
31157
|
return /*#__PURE__*/React.createElement(MovablePointView, {
|
|
31153
31158
|
ref: elementRef,
|
|
@@ -31163,8 +31168,10 @@ const StyledMovablePoint = props => {
|
|
|
31163
31168
|
};
|
|
31164
31169
|
|
|
31165
31170
|
const PolygonGraph = props => {
|
|
31166
|
-
const [focused, setFocused] = React.useState(false);
|
|
31167
31171
|
const [hovered, setHovered] = React.useState(false);
|
|
31172
|
+
// This is more so required for the re-rendering that occurs when state
|
|
31173
|
+
// updates; specifically with regard to line weighting and polygon focus.
|
|
31174
|
+
const [focusVisible, setFocusVisible] = React.useState(false);
|
|
31168
31175
|
const {
|
|
31169
31176
|
dispatch
|
|
31170
31177
|
} = props;
|
|
@@ -31174,10 +31181,10 @@ const PolygonGraph = props => {
|
|
|
31174
31181
|
showSides,
|
|
31175
31182
|
range,
|
|
31176
31183
|
snapStep,
|
|
31177
|
-
snapTo
|
|
31184
|
+
snapTo = "grid"
|
|
31178
31185
|
} = props.graphState;
|
|
31179
31186
|
const {
|
|
31180
|
-
|
|
31187
|
+
disableKeyboardInteraction
|
|
31181
31188
|
} = useGraphConfig();
|
|
31182
31189
|
|
|
31183
31190
|
// TODO(benchristel): can the default set of points be removed here? I don't
|
|
@@ -31185,7 +31192,7 @@ const PolygonGraph = props => {
|
|
|
31185
31192
|
const points = coords != null ? coords : [[0, 0]];
|
|
31186
31193
|
const ref = React.useRef(null);
|
|
31187
31194
|
const dragReferencePoint = points[0];
|
|
31188
|
-
const
|
|
31195
|
+
const constrain = ["angles", "sides"].includes(snapTo) ? p => p : p => snap(snapStep, p);
|
|
31189
31196
|
const {
|
|
31190
31197
|
dragging
|
|
31191
31198
|
} = useDraggable({
|
|
@@ -31195,16 +31202,15 @@ const PolygonGraph = props => {
|
|
|
31195
31202
|
const delta = vec.sub(newPoint, dragReferencePoint);
|
|
31196
31203
|
dispatch(actions.polygon.moveAll(delta));
|
|
31197
31204
|
},
|
|
31198
|
-
|
|
31205
|
+
constrainKeyboardMovement: constrain
|
|
31199
31206
|
});
|
|
31200
|
-
const active = hovered || focused || dragging;
|
|
31201
31207
|
const lastMoveTime = React.useRef(0);
|
|
31202
31208
|
const lines = getLines(points);
|
|
31203
31209
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Polygon, {
|
|
31204
31210
|
points: [...points],
|
|
31205
31211
|
color: "var(--movable-line-stroke-color)",
|
|
31206
31212
|
svgPolygonProps: {
|
|
31207
|
-
strokeWidth:
|
|
31213
|
+
strokeWidth: focusVisible ? "var(--movable-line-stroke-weight-active)" : "var(--movable-line-stroke-weight)",
|
|
31208
31214
|
style: {
|
|
31209
31215
|
fill: "transparent"
|
|
31210
31216
|
}
|
|
@@ -31219,11 +31225,10 @@ const PolygonGraph = props => {
|
|
|
31219
31225
|
key: "angle-" + i,
|
|
31220
31226
|
centerPoint: point,
|
|
31221
31227
|
endPoints: [pt1, pt2],
|
|
31222
|
-
active: active,
|
|
31223
31228
|
range: range,
|
|
31224
31229
|
polygonLines: lines,
|
|
31225
31230
|
showAngles: !!showAngles,
|
|
31226
|
-
snapTo:
|
|
31231
|
+
snapTo: snapTo
|
|
31227
31232
|
});
|
|
31228
31233
|
}), showSides && lines.map(([start, end], i) => {
|
|
31229
31234
|
const [x, y] = vec.midpoint(start, end);
|
|
@@ -31238,21 +31243,29 @@ const PolygonGraph = props => {
|
|
|
31238
31243
|
color: "transparent",
|
|
31239
31244
|
svgPolygonProps: {
|
|
31240
31245
|
ref,
|
|
31241
|
-
tabIndex:
|
|
31246
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
31242
31247
|
strokeWidth: TARGET_SIZE,
|
|
31243
31248
|
style: {
|
|
31244
31249
|
cursor: dragging ? "grabbing" : "grab",
|
|
31245
31250
|
fill: hovered ? "var(--mafs-blue)" : "transparent"
|
|
31246
31251
|
},
|
|
31247
|
-
onFocus: () => setFocused(true),
|
|
31248
|
-
onBlur: () => setFocused(false),
|
|
31249
31252
|
onMouseEnter: () => setHovered(true),
|
|
31250
31253
|
onMouseLeave: () => setHovered(false),
|
|
31254
|
+
// Required to remove line weighting when user clicks away
|
|
31255
|
+
// from the focused polygon
|
|
31256
|
+
onKeyDownCapture: () => {
|
|
31257
|
+
setFocusVisible(hasFocusVisible(ref.current));
|
|
31258
|
+
},
|
|
31259
|
+
// Required for lines to darken on focus
|
|
31260
|
+
onFocus: () => setFocusVisible(hasFocusVisible(ref.current)),
|
|
31261
|
+
// Required for line weighting to update on blur. Without this,
|
|
31262
|
+
// the user has to hover over the shape for it to update
|
|
31263
|
+
onBlur: () => setFocusVisible(hasFocusVisible(ref.current)),
|
|
31251
31264
|
className: "movable-polygon"
|
|
31252
31265
|
}
|
|
31253
|
-
}), points.map((point, i) => /*#__PURE__*/React.createElement(
|
|
31266
|
+
}), points.map((point, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31254
31267
|
key: "point-" + i,
|
|
31255
|
-
|
|
31268
|
+
constrain: constrain,
|
|
31256
31269
|
point: point,
|
|
31257
31270
|
onMove: destination => {
|
|
31258
31271
|
const now = Date.now();
|
|
@@ -31271,6 +31284,20 @@ function getLines(points) {
|
|
|
31271
31284
|
return [point, next];
|
|
31272
31285
|
});
|
|
31273
31286
|
}
|
|
31287
|
+
const hasFocusVisible = element => {
|
|
31288
|
+
const matches = selector => {
|
|
31289
|
+
var _element$matches;
|
|
31290
|
+
return (_element$matches = element == null ? void 0 : element.matches(selector)) != null ? _element$matches : false;
|
|
31291
|
+
};
|
|
31292
|
+
try {
|
|
31293
|
+
return matches(":focus-visible");
|
|
31294
|
+
} catch (e) {
|
|
31295
|
+
// jsdom doesn't support :focus-visible
|
|
31296
|
+
// (see https://github.com/jsdom/jsdom/issues/3426),
|
|
31297
|
+
// so the call to matches(":focus-visible") will fail in tests.
|
|
31298
|
+
return matches(":focus");
|
|
31299
|
+
}
|
|
31300
|
+
};
|
|
31274
31301
|
|
|
31275
31302
|
function getGradableGraph(state, initialGraph) {
|
|
31276
31303
|
if (!state.hasBeenInteractedWith) {
|
|
@@ -31364,7 +31391,7 @@ function CircleGraph(props) {
|
|
|
31364
31391
|
center: center,
|
|
31365
31392
|
radius: getRadius(graphState),
|
|
31366
31393
|
onMove: c => dispatch(actions.circle.moveCenter(c))
|
|
31367
|
-
}), /*#__PURE__*/React.createElement(
|
|
31394
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31368
31395
|
point: radiusPoint,
|
|
31369
31396
|
cursor: "ew-resize",
|
|
31370
31397
|
onMove: newRadiusPoint => {
|
|
@@ -31380,7 +31407,7 @@ function MovableCircle(props) {
|
|
|
31380
31407
|
} = props;
|
|
31381
31408
|
const {
|
|
31382
31409
|
snapStep,
|
|
31383
|
-
|
|
31410
|
+
disableKeyboardInteraction
|
|
31384
31411
|
} = useGraphConfig();
|
|
31385
31412
|
const draggableRef = useRef(null);
|
|
31386
31413
|
const {
|
|
@@ -31389,13 +31416,13 @@ function MovableCircle(props) {
|
|
|
31389
31416
|
gestureTarget: draggableRef,
|
|
31390
31417
|
point: center,
|
|
31391
31418
|
onMove,
|
|
31392
|
-
|
|
31419
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
31393
31420
|
});
|
|
31394
31421
|
const [centerPx] = useTransformVectorsToPixels(center);
|
|
31395
31422
|
const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
|
|
31396
31423
|
return /*#__PURE__*/React.createElement("g", {
|
|
31397
31424
|
ref: draggableRef,
|
|
31398
|
-
tabIndex:
|
|
31425
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
31399
31426
|
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
|
|
31400
31427
|
}, /*#__PURE__*/React.createElement("ellipse", {
|
|
31401
31428
|
className: "focus-ring",
|
|
@@ -31476,7 +31503,7 @@ function QuadraticGraph(props) {
|
|
|
31476
31503
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Plot$3.OfX, {
|
|
31477
31504
|
y: y,
|
|
31478
31505
|
color: color.blue
|
|
31479
|
-
}), coords.map((coord, i) => /*#__PURE__*/React.createElement(
|
|
31506
|
+
}), coords.map((coord, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31480
31507
|
key: "point-" + i,
|
|
31481
31508
|
point: coord,
|
|
31482
31509
|
onMove: destination => dispatch(actions.quadratic.movePoint(i, destination))
|
|
@@ -31536,7 +31563,7 @@ function SinusoidGraph(props) {
|
|
|
31536
31563
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Plot$3.OfX, {
|
|
31537
31564
|
y: x => computeSine(x, coeffRef.current),
|
|
31538
31565
|
color: color.blue
|
|
31539
|
-
}), coords.map((coord, i) => /*#__PURE__*/React.createElement(
|
|
31566
|
+
}), coords.map((coord, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31540
31567
|
key: "point-" + i,
|
|
31541
31568
|
point: coord,
|
|
31542
31569
|
onMove: destination => dispatch(actions.sinusoid.movePoint(i, destination))
|
|
@@ -31592,7 +31619,6 @@ function AngleGraph(props) {
|
|
|
31592
31619
|
showAngles,
|
|
31593
31620
|
range,
|
|
31594
31621
|
allowReflexAngles,
|
|
31595
|
-
angleOffsetDeg,
|
|
31596
31622
|
snapDegrees
|
|
31597
31623
|
} = graphState;
|
|
31598
31624
|
|
|
@@ -31630,8 +31656,6 @@ function AngleGraph(props) {
|
|
|
31630
31656
|
coords: endPoints,
|
|
31631
31657
|
allowReflexAngles: allowReflexAngles || false,
|
|
31632
31658
|
// Whether to allow reflex angles or not
|
|
31633
|
-
angleOffsetDeg: angleOffsetDeg || 0,
|
|
31634
|
-
// The angle offset from the x-axis
|
|
31635
31659
|
snapDegrees: snapDegrees || 1,
|
|
31636
31660
|
// The multiple of degrees to snap to
|
|
31637
31661
|
range: range,
|
|
@@ -31639,19 +31663,66 @@ function AngleGraph(props) {
|
|
|
31639
31663
|
};
|
|
31640
31664
|
|
|
31641
31665
|
// Render the lines, angle, and then movable points
|
|
31642
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, svgLines, /*#__PURE__*/React.createElement(Angle, angleParams),
|
|
31643
|
-
|
|
31644
|
-
|
|
31645
|
-
|
|
31646
|
-
|
|
31647
|
-
|
|
31666
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, svgLines, /*#__PURE__*/React.createElement(Angle, angleParams), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31667
|
+
point: coords[1],
|
|
31668
|
+
constrain: p => p,
|
|
31669
|
+
onMove: destination => dispatch(actions.angle.movePoint(1, destination))
|
|
31670
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31671
|
+
point: coords[0],
|
|
31672
|
+
constrain: getAngleSideConstraint(coords[0], coords[1], snapDegrees || 1),
|
|
31673
|
+
onMove: destination => dispatch(actions.angle.movePoint(0, destination))
|
|
31674
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31675
|
+
point: coords[2],
|
|
31676
|
+
constrain: getAngleSideConstraint(coords[2], coords[1], snapDegrees || 1),
|
|
31677
|
+
onMove: destination => dispatch(actions.angle.movePoint(2, destination))
|
|
31678
|
+
}));
|
|
31679
|
+
}
|
|
31680
|
+
const positiveX = [1, 0];
|
|
31681
|
+
const negativeX = [-1, 0];
|
|
31682
|
+
const positiveY = [0, 1];
|
|
31683
|
+
const negativeY = [0, -1];
|
|
31684
|
+
function getAngleSideConstraint(sidePoint, vertex, snapDegrees) {
|
|
31685
|
+
var _findIntersectionOfRa, _findIntersectionOfRa2, _findIntersectionOfRa3, _findIntersectionOfRa4;
|
|
31686
|
+
const currentAngle = calculateAngleInDegrees(vec.sub(sidePoint, vertex));
|
|
31687
|
+
|
|
31688
|
+
// Find the rays that start at the current point and point up, down, left
|
|
31689
|
+
// and right.
|
|
31690
|
+
const leftRay = [sidePoint, vec.add(sidePoint, negativeX)];
|
|
31691
|
+
const rightRay = [sidePoint, vec.add(sidePoint, positiveX)];
|
|
31692
|
+
const upRay = [sidePoint, vec.add(sidePoint, positiveY)];
|
|
31693
|
+
const downRay = [sidePoint, vec.add(sidePoint, negativeY)];
|
|
31694
|
+
|
|
31695
|
+
// find the angles that lie one snap step clockwise and counter-clockwise
|
|
31696
|
+
// from the current angle. These are the angles to which the side can be
|
|
31697
|
+
// moved.
|
|
31698
|
+
const oneStepCounterClockwise = currentAngle + snapDegrees;
|
|
31699
|
+
const oneStepClockwise = currentAngle - snapDegrees;
|
|
31700
|
+
|
|
31701
|
+
// find the rays that start from the vertex and point in the direction of
|
|
31702
|
+
// the angles we just computed.
|
|
31703
|
+
const counterClockwiseRay = [vertex, vec.add(vertex, polar(1, oneStepCounterClockwise))];
|
|
31704
|
+
const clockwiseRay = [vertex, vec.add(vertex, polar(1, oneStepClockwise))];
|
|
31705
|
+
|
|
31706
|
+
// find the intersections of those rays with the horizontal and vertical
|
|
31707
|
+
// rays extending from the sidePoint. These intersections are the points to
|
|
31708
|
+
// which sidePoint can move that will result in a rotation of `snapDegrees`.
|
|
31709
|
+
const left = (_findIntersectionOfRa = findIntersectionOfRays(leftRay, counterClockwiseRay)) != null ? _findIntersectionOfRa : findIntersectionOfRays(leftRay, clockwiseRay);
|
|
31710
|
+
const right = (_findIntersectionOfRa2 = findIntersectionOfRays(rightRay, counterClockwiseRay)) != null ? _findIntersectionOfRa2 : findIntersectionOfRays(rightRay, clockwiseRay);
|
|
31711
|
+
const up = (_findIntersectionOfRa3 = findIntersectionOfRays(upRay, counterClockwiseRay)) != null ? _findIntersectionOfRa3 : findIntersectionOfRays(upRay, clockwiseRay);
|
|
31712
|
+
const down = (_findIntersectionOfRa4 = findIntersectionOfRays(downRay, counterClockwiseRay)) != null ? _findIntersectionOfRa4 : findIntersectionOfRays(downRay, clockwiseRay);
|
|
31713
|
+
return {
|
|
31714
|
+
up: up != null ? up : sidePoint,
|
|
31715
|
+
down: down != null ? down : sidePoint,
|
|
31716
|
+
left: left != null ? left : sidePoint,
|
|
31717
|
+
right: right != null ? right : sidePoint
|
|
31718
|
+
};
|
|
31648
31719
|
}
|
|
31649
31720
|
|
|
31650
31721
|
function PointGraph(props) {
|
|
31651
31722
|
const {
|
|
31652
31723
|
dispatch
|
|
31653
31724
|
} = props;
|
|
31654
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, props.graphState.coords.map((point, i) => /*#__PURE__*/React.createElement(
|
|
31725
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, props.graphState.coords.map((point, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31655
31726
|
key: i,
|
|
31656
31727
|
point: point,
|
|
31657
31728
|
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination))
|
|
@@ -31683,7 +31754,7 @@ function Protractor() {
|
|
|
31683
31754
|
gestureTarget: draggableRef,
|
|
31684
31755
|
onMove: setCenter,
|
|
31685
31756
|
point: center,
|
|
31686
|
-
|
|
31757
|
+
constrainKeyboardMovement: point => bound$1({
|
|
31687
31758
|
snapStep,
|
|
31688
31759
|
range,
|
|
31689
31760
|
point
|
|
@@ -31799,7 +31870,8 @@ const MafsGraph = props => {
|
|
|
31799
31870
|
state,
|
|
31800
31871
|
dispatch,
|
|
31801
31872
|
labels,
|
|
31802
|
-
hintMode
|
|
31873
|
+
hintMode,
|
|
31874
|
+
readOnly
|
|
31803
31875
|
} = props;
|
|
31804
31876
|
const [width, height] = props.box;
|
|
31805
31877
|
const tickStep = props.step;
|
|
@@ -31815,7 +31887,7 @@ const MafsGraph = props => {
|
|
|
31815
31887
|
width,
|
|
31816
31888
|
height,
|
|
31817
31889
|
labels,
|
|
31818
|
-
hintMode
|
|
31890
|
+
disableKeyboardInteraction: hintMode || readOnly
|
|
31819
31891
|
}
|
|
31820
31892
|
}, /*#__PURE__*/React.createElement(View, {
|
|
31821
31893
|
className: "mafs-graph",
|
|
@@ -32173,6 +32245,9 @@ const getAngleCoords = params => {
|
|
|
32173
32245
|
if (graph.coords) {
|
|
32174
32246
|
return graph.coords;
|
|
32175
32247
|
}
|
|
32248
|
+
if (graph.startCoords) {
|
|
32249
|
+
return graph.startCoords;
|
|
32250
|
+
}
|
|
32176
32251
|
const {
|
|
32177
32252
|
snapDegrees,
|
|
32178
32253
|
angleOffsetDeg
|
|
@@ -32202,6 +32277,7 @@ const getAngleCoords = params => {
|
|
|
32202
32277
|
return coords;
|
|
32203
32278
|
};
|
|
32204
32279
|
|
|
32280
|
+
const minDistanceBetweenAngleVertexAndSidePoint = 2;
|
|
32205
32281
|
function interactiveGraphReducer(state, action) {
|
|
32206
32282
|
switch (action.type) {
|
|
32207
32283
|
case REINITIALIZE:
|
|
@@ -32367,21 +32443,28 @@ function doMovePoint(state, action) {
|
|
|
32367
32443
|
case "angle":
|
|
32368
32444
|
// If the index is 1, we are moving the vertex of the angle,
|
|
32369
32445
|
// which will move the other two points as well
|
|
32370
|
-
|
|
32371
|
-
|
|
32446
|
+
const newState = (() => {
|
|
32447
|
+
if (action.index === 1) {
|
|
32448
|
+
const updatedCoords = boundAndSnapAngleVertex(state, action);
|
|
32449
|
+
return _extends({}, state, {
|
|
32450
|
+
hasBeenInteractedWith: true,
|
|
32451
|
+
coords: updatedCoords
|
|
32452
|
+
});
|
|
32453
|
+
}
|
|
32372
32454
|
return _extends({}, state, {
|
|
32373
32455
|
hasBeenInteractedWith: true,
|
|
32374
|
-
coords:
|
|
32456
|
+
coords: setAtIndex({
|
|
32457
|
+
array: state.coords,
|
|
32458
|
+
index: action.index,
|
|
32459
|
+
newValue: boundAndSnapAngleEndPoints(action.destination, state, action.index)
|
|
32460
|
+
})
|
|
32375
32461
|
});
|
|
32462
|
+
})();
|
|
32463
|
+
if (angleSidePointsTooCloseToVertex(newState)) {
|
|
32464
|
+
// cancel the move
|
|
32465
|
+
return state;
|
|
32376
32466
|
}
|
|
32377
|
-
return
|
|
32378
|
-
hasBeenInteractedWith: true,
|
|
32379
|
-
coords: setAtIndex({
|
|
32380
|
-
array: state.coords,
|
|
32381
|
-
index: action.index,
|
|
32382
|
-
newValue: boundAndSnapAngleEndPoints(action.destination, state, action.index)
|
|
32383
|
-
})
|
|
32384
|
-
});
|
|
32467
|
+
return newState;
|
|
32385
32468
|
case "polygon":
|
|
32386
32469
|
let newValue;
|
|
32387
32470
|
if (state.snapTo === "sides") {
|
|
@@ -32470,11 +32553,7 @@ function doMoveCenter(state, action) {
|
|
|
32470
32553
|
case "circle":
|
|
32471
32554
|
{
|
|
32472
32555
|
// Constrain the center of the circle to the chart range
|
|
32473
|
-
const constrainedCenter =
|
|
32474
|
-
snapStep: state.snapStep,
|
|
32475
|
-
range: state.range,
|
|
32476
|
-
point: action.destination
|
|
32477
|
-
});
|
|
32556
|
+
const constrainedCenter = boundAndSnapToGrid(action.destination, state);
|
|
32478
32557
|
|
|
32479
32558
|
// Reposition the radius point based on the new center
|
|
32480
32559
|
// (spread to make sure we're not going to mutate anything)
|
|
@@ -32508,10 +32587,10 @@ function doMoveRadiusPoint(state, action) {
|
|
|
32508
32587
|
case "circle":
|
|
32509
32588
|
{
|
|
32510
32589
|
const [xMin, xMax] = state.range[X];
|
|
32511
|
-
const nextRadiusPoint = [
|
|
32590
|
+
const nextRadiusPoint = snap(state.snapStep, [
|
|
32512
32591
|
// Constrain to graph range
|
|
32513
32592
|
// The +0 is to convert -0 to +0
|
|
32514
|
-
clamp(action.destination[X] + 0, xMin, xMax), state.center[1]];
|
|
32593
|
+
clamp(action.destination[X] + 0, xMin, xMax), state.center[1]]);
|
|
32515
32594
|
if (_.isEqual(nextRadiusPoint, state.center)) {
|
|
32516
32595
|
return state;
|
|
32517
32596
|
}
|
|
@@ -32593,17 +32672,16 @@ function boundAndSnapAngleVertex({
|
|
|
32593
32672
|
|
|
32594
32673
|
// Get the current and upcoming positions of the vertex
|
|
32595
32674
|
const startingVertex = coordsCopy[1];
|
|
32596
|
-
|
|
32597
|
-
|
|
32598
|
-
|
|
32599
|
-
|
|
32600
|
-
|
|
32675
|
+
|
|
32676
|
+
// Prevent the vertex from getting too close to the edge, so that all
|
|
32677
|
+
// points of the angle can fit within the graph bounds.
|
|
32678
|
+
const insetAmount = vec.add(snapStep, [minDistanceBetweenAngleVertexAndSidePoint, minDistanceBetweenAngleVertexAndSidePoint]);
|
|
32679
|
+
const newVertex = clampToBox(inset(insetAmount, range), snap(snapStep, destination));
|
|
32601
32680
|
|
|
32602
32681
|
// Get the vector from the starting vertex to the new vertex
|
|
32603
32682
|
const delta = vec.add(newVertex, reverseVector(startingVertex));
|
|
32604
32683
|
|
|
32605
32684
|
// Apply the delta to each of the other two points so that the angle is maintained
|
|
32606
|
-
let valid = true;
|
|
32607
32685
|
const newPoints = {};
|
|
32608
32686
|
for (const i of [0, 2]) {
|
|
32609
32687
|
const oldPoint = coordsCopy[i];
|
|
@@ -32612,21 +32690,13 @@ function boundAndSnapAngleVertex({
|
|
|
32612
32690
|
angle *= Math.PI / 180;
|
|
32613
32691
|
newPoint = constrainToBoundsOnAngle(newPoint, angle, range, snapStep);
|
|
32614
32692
|
newPoints[i] = newPoint;
|
|
32615
|
-
|
|
32616
|
-
// Check if the new point is too close to the vertex
|
|
32617
|
-
if (tooClose(newVertex, newPoint)) {
|
|
32618
|
-
valid = false;
|
|
32619
|
-
}
|
|
32620
32693
|
}
|
|
32621
32694
|
|
|
32622
32695
|
// Update the vertex after snapping to the snapStep
|
|
32623
32696
|
newPoints[1] = newVertex;
|
|
32624
|
-
|
|
32625
|
-
|
|
32626
|
-
|
|
32627
|
-
coordsCopy[i] = newPoint;
|
|
32628
|
-
});
|
|
32629
|
-
}
|
|
32697
|
+
Object.entries(newPoints).forEach(([i, newPoint]) => {
|
|
32698
|
+
coordsCopy[i] = newPoint;
|
|
32699
|
+
});
|
|
32630
32700
|
return coordsCopy;
|
|
32631
32701
|
}
|
|
32632
32702
|
|
|
@@ -32691,10 +32761,17 @@ function boundAndSnapAngleEndPoints(destinationPoint, {
|
|
|
32691
32761
|
|
|
32692
32762
|
// Snap the angle to the nearest multiple of snapDegrees (if provided)
|
|
32693
32763
|
angle = Math.round((angle - offsetDegrees) / snap) * snap + offsetDegrees;
|
|
32694
|
-
|
|
32764
|
+
|
|
32765
|
+
// add 0.01 to prevent rounding errors from causing the point to snap to
|
|
32766
|
+
// a location that is too close to the vertex.
|
|
32767
|
+
const minDistance = minDistanceBetweenAngleVertexAndSidePoint + 0.01;
|
|
32768
|
+
const distance = Math.max(vec.dist(coordsCopy[index], vertex), minDistance);
|
|
32695
32769
|
const snappedValue = vec.add(vertex, polar(distance, angle));
|
|
32696
32770
|
return snappedValue;
|
|
32697
32771
|
}
|
|
32772
|
+
function angleSidePointsTooCloseToVertex(state) {
|
|
32773
|
+
return tooClose(state.coords[0], state.coords[1], state.range) || tooClose(state.coords[2], state.coords[1], state.range);
|
|
32774
|
+
}
|
|
32698
32775
|
function boundAndSnapToPolygonAngle(destinationPoint, {
|
|
32699
32776
|
range,
|
|
32700
32777
|
coords
|
|
@@ -32917,7 +32994,12 @@ const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
32917
32994
|
useEffect(() => {
|
|
32918
32995
|
dispatch(changeRange([[xMinRange, xMaxRange], [yMinRange, yMaxRange]]));
|
|
32919
32996
|
}, [dispatch, xMinRange, xMaxRange, yMinRange, yMaxRange]);
|
|
32997
|
+
|
|
32998
|
+
// Update the graph whenever any of the following values changes.
|
|
32999
|
+
// This is necessary to keep the graph previews in sync with the updated
|
|
33000
|
+
// graph settings within the interative graph editor.
|
|
32920
33001
|
const numSegments = graph.type === "segment" ? graph.numSegments : null;
|
|
33002
|
+
const numPoints = graph.type === "point" ? graph.numPoints : null;
|
|
32921
33003
|
const numSides = graph.type === "polygon" ? graph.numSides : null;
|
|
32922
33004
|
const snapTo = graph.type === "polygon" ? graph.snapTo : null;
|
|
32923
33005
|
const showAngles = graph.type === "polygon" ? graph.showAngles : null;
|
|
@@ -32932,7 +33014,7 @@ const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
32932
33014
|
if (latestPropsRef.current !== originalPropsRef.current) {
|
|
32933
33015
|
dispatch(reinitialize(latestPropsRef.current));
|
|
32934
33016
|
}
|
|
32935
|
-
}, [graph.type, numSegments, numSides, snapTo, showAngles, showSides, latestPropsRef, graph.startCoords]);
|
|
33017
|
+
}, [graph.type, numPoints, numSegments, numSides, snapTo, showAngles, showSides, latestPropsRef, graph.startCoords]);
|
|
32936
33018
|
return /*#__PURE__*/React.createElement(MafsGraph, _extends({}, props, {
|
|
32937
33019
|
state: state,
|
|
32938
33020
|
dispatch: dispatch
|
|
@@ -34242,6 +34324,7 @@ class InteractiveGraph extends React.Component {
|
|
|
34242
34324
|
// Mafs shim
|
|
34243
34325
|
const mafsFlags = (_this$props$apiOption = this.props.apiOptions) == null || (_this$props$apiOption = _this$props$apiOption.flags) == null ? void 0 : _this$props$apiOption["mafs"];
|
|
34244
34326
|
if (shouldUseMafs(mafsFlags, this.props.graph)) {
|
|
34327
|
+
var _this$props$apiOption2;
|
|
34245
34328
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
34246
34329
|
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
34247
34330
|
const snapStep = this.props.snapStep || Util.snapStepFromGridStep(gridStep);
|
|
@@ -34251,7 +34334,8 @@ class InteractiveGraph extends React.Component {
|
|
|
34251
34334
|
snapStep: snapStep,
|
|
34252
34335
|
box: box,
|
|
34253
34336
|
showTooltips: !!this.props.showTooltips,
|
|
34254
|
-
hintMode: this.props.hintMode
|
|
34337
|
+
hintMode: this.props.hintMode,
|
|
34338
|
+
readOnly: (_this$props$apiOption2 = this.props.apiOptions) == null ? void 0 : _this$props$apiOption2.readOnly
|
|
34255
34339
|
}));
|
|
34256
34340
|
}
|
|
34257
34341
|
return /*#__PURE__*/React.createElement(LegacyInteractiveGraph, _extends({
|
|
@@ -44170,7 +44254,7 @@ const init = function init(options) {
|
|
|
44170
44254
|
|
|
44171
44255
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44172
44256
|
const libName = "@khanacademy/perseus";
|
|
44173
|
-
const libVersion = "
|
|
44257
|
+
const libVersion = "28.0.0";
|
|
44174
44258
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44175
44259
|
|
|
44176
44260
|
const apiVersion = {
|
|
@@ -44725,7 +44809,6 @@ const context = /*#__PURE__*/React.createContext(defaultContext);
|
|
|
44725
44809
|
const {
|
|
44726
44810
|
mapObject
|
|
44727
44811
|
} = objective_;
|
|
44728
|
-
/* eslint-disable-next-line react/no-unsafe */
|
|
44729
44812
|
class ServerItemRenderer extends React.Component {
|
|
44730
44813
|
constructor(props) {
|
|
44731
44814
|
super(props);
|
|
@@ -46091,7 +46174,16 @@ class MultiRenderer extends React.Component {
|
|
|
46091
46174
|
// _annotateRendererArray() needs this
|
|
46092
46175
|
ref: null,
|
|
46093
46176
|
makeRenderer: () => /*#__PURE__*/React.createElement(HintsRenderer, _extends({}, this._getRendererProps(), {
|
|
46094
|
-
findExternalWidgets: findExternalWidgets
|
|
46177
|
+
findExternalWidgets: findExternalWidgets
|
|
46178
|
+
// Note(Jeremy): The MultiRenderer codebase types are
|
|
46179
|
+
// slightly different from the rest of the codebase.
|
|
46180
|
+
// Ideally `HintNode` would spread the `Hint` type into it,
|
|
46181
|
+
// but there is a difference in optionality of `widgets`
|
|
46182
|
+
// and `images` and that causes a huge cascade of type
|
|
46183
|
+
// errors (they are truly optional, but most of our code
|
|
46184
|
+
// assumes they're provided/set). Ignoring this for now.
|
|
46185
|
+
// @ts-expect-error - TS2769 - Type 'HintNode' is not assignable to type 'Hint'.
|
|
46186
|
+
,
|
|
46095
46187
|
hints: [hint]
|
|
46096
46188
|
}))
|
|
46097
46189
|
};
|
|
@@ -47750,5 +47842,5 @@ const EditorJsonify = {
|
|
|
47750
47842
|
}
|
|
47751
47843
|
};
|
|
47752
47844
|
|
|
47753
|
-
export { ApiOptions, ArrowPicker, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, ColorPicker, DashPicker, dependencies as Dependencies, EditorJsonify, ElementContainer, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusExpressionAnswerFormConsidered, PerseusI18nContext, PerseusI18nContextProvider, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, WidgetJsonifyDeprecated, widgets$1 as Widgets, addWidget, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, contentHasWidgetType, convertWidgetNameToEnum, displaySigFigs, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestInteractiveGraphWidget, generateTestNumericInputWidget, generateTestPerseusItem, generateTestRadioWidget, genericPerseusItemData, getAnswerFromUserInput, getAnswersFromWidgets, getCircleCoords, getCorrectAnswerForWidgetId, getLineCoords, getLinearSystemCoords, getQuadraticCoords, getSegmentCoords, getSinusoidCoords, getValidWidgetIds, getWidgetFromWidgetMap, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetTypeByWidgetId, getWidgetsFromWidgetMap, getWidgetsMapFromItemData, globalConstants, globalStyles, iconPaths as icons, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, isWidgetIdInContent, isWrongAnswerSupported, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, lockedFigureColors, lockedFigureFillStyles, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, shouldHaveIndividualAnswer, traverse, usePerseusI18n, violatingWidgets, allWidgets as widgets };
|
|
47845
|
+
export { ApiOptions, ArrowPicker, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, ColorPicker, DashPicker, dependencies as Dependencies, EditorJsonify, ElementContainer, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusExpressionAnswerFormConsidered, PerseusI18nContext, PerseusI18nContextProvider, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, WidgetJsonifyDeprecated, widgets$1 as Widgets, addWidget, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, contentHasWidgetType, convertWidgetNameToEnum, displaySigFigs, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestInteractiveGraphWidget, generateTestNumericInputWidget, generateTestPerseusItem, generateTestRadioWidget, genericPerseusItemData, getAngleCoords, getAnswerFromUserInput, getAnswersFromWidgets, getCircleCoords, getCorrectAnswerForWidgetId, getLineCoords, getLinearSystemCoords, getPointCoords, getPolygonCoords, getQuadraticCoords, getSegmentCoords, getSinusoidCoords, getValidWidgetIds, getWidgetFromWidgetMap, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetTypeByWidgetId, getWidgetsFromWidgetMap, getWidgetsMapFromItemData, globalConstants, globalStyles, iconPaths as icons, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, isWidgetIdInContent, isWrongAnswerSupported, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, lockedFigureColors, lockedFigureFillStyles, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, shouldHaveIndividualAnswer, traverse, usePerseusI18n, violatingWidgets, allWidgets as widgets };
|
|
47754
47846
|
//# sourceMappingURL=index.js.map
|