@khanacademy/perseus 27.2.0 → 28.1.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 +452 -362
- 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 +438 -348
- 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 +8 -7
- 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",
|
|
@@ -640,9 +669,11 @@ const styles$E = StyleSheet.create({
|
|
|
640
669
|
borderRadius: 1
|
|
641
670
|
},
|
|
642
671
|
iconInactive: {
|
|
672
|
+
border: "2px solid transparent",
|
|
643
673
|
backgroundColor: color.offBlack8
|
|
644
674
|
},
|
|
645
675
|
iconActive: {
|
|
676
|
+
border: `2px solid ${color.white}`,
|
|
646
677
|
backgroundColor: color.offBlack64
|
|
647
678
|
},
|
|
648
679
|
outerWrapper: {
|
|
@@ -1161,26 +1192,6 @@ const ClassNames = {
|
|
|
1161
1192
|
MOBILE: "perseus-mobile"
|
|
1162
1193
|
};
|
|
1163
1194
|
|
|
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
1195
|
const KhanMath = {
|
|
1185
1196
|
// Simplify formulas before display
|
|
1186
1197
|
cleanMath: function (expr) {
|
|
@@ -2475,7 +2486,7 @@ class Expression extends React.Component {
|
|
|
2475
2486
|
var _this$props$keypadCon, _this$props$analytics3;
|
|
2476
2487
|
if (this.props.apiOptions.customKeypad) {
|
|
2477
2488
|
return /*#__PURE__*/React.createElement(View, {
|
|
2478
|
-
className: css(styles$
|
|
2489
|
+
className: css(styles$C.mobileLabelInputWrapper)
|
|
2479
2490
|
}, !!this.props.visibleLabel && /*#__PURE__*/React.createElement(LabelSmall, {
|
|
2480
2491
|
htmlFor: this._textareaId,
|
|
2481
2492
|
tag: "label"
|
|
@@ -2510,7 +2521,7 @@ class Expression extends React.Component {
|
|
|
2510
2521
|
ERROR_TITLE
|
|
2511
2522
|
} = this.context.strings;
|
|
2512
2523
|
return /*#__PURE__*/React.createElement(View, {
|
|
2513
|
-
className: css(styles$
|
|
2524
|
+
className: css(styles$C.desktopLabelInputWrapper)
|
|
2514
2525
|
}, !!this.props.visibleLabel && /*#__PURE__*/React.createElement(LabelSmall, {
|
|
2515
2526
|
htmlFor: this._textareaId,
|
|
2516
2527
|
tag: "label"
|
|
@@ -2562,7 +2573,7 @@ Expression.defaultProps = {
|
|
|
2562
2573
|
apiOptions: ApiOptions.defaults,
|
|
2563
2574
|
linterContext: linterContextDefault
|
|
2564
2575
|
};
|
|
2565
|
-
const styles$
|
|
2576
|
+
const styles$C = StyleSheet.create({
|
|
2566
2577
|
mobileLabelInputWrapper: {
|
|
2567
2578
|
padding: "15px 4px 0"
|
|
2568
2579
|
},
|
|
@@ -8942,8 +8953,8 @@ function findChildOrAdd(elem, className) {
|
|
|
8942
8953
|
return $child;
|
|
8943
8954
|
}
|
|
8944
8955
|
var Tex$1 = {
|
|
8945
|
-
// Process a node and add math inside of it. This
|
|
8946
|
-
// format the math
|
|
8956
|
+
// Process a node and add math inside of it. This uses MathJax to
|
|
8957
|
+
// format the math.
|
|
8947
8958
|
//
|
|
8948
8959
|
// elem: The element which the math should be added to.
|
|
8949
8960
|
//
|
|
@@ -15305,7 +15316,7 @@ const DEFAULT_STATE$1 = {
|
|
|
15305
15316
|
// TODO(benchristel): this is a memory leak. We add items to
|
|
15306
15317
|
// tooltipResetFunctions, but never remove them.
|
|
15307
15318
|
const tooltipResetFunctions = [];
|
|
15308
|
-
class MovablePoint$
|
|
15319
|
+
class MovablePoint$5 {
|
|
15309
15320
|
constructor(graphie, movable, options) {
|
|
15310
15321
|
this.graphie = void 0;
|
|
15311
15322
|
this.movable = void 0;
|
|
@@ -15600,9 +15611,9 @@ class MovablePoint$4 {
|
|
|
15600
15611
|
* Displays a tooltip above the point, replacing any previous contents. If
|
|
15601
15612
|
* there is no tooltip initialized, adds the tooltip.
|
|
15602
15613
|
*
|
|
15603
|
-
* If the type of contents is string, the contents will be rendered
|
|
15604
|
-
*
|
|
15605
|
-
*
|
|
15614
|
+
* If the type of contents is string, the contents will be rendered as TeX
|
|
15615
|
+
* Otherwise, the content will be assumed to be a DOM node and will be
|
|
15616
|
+
* appended inside the tooltip.
|
|
15606
15617
|
*/
|
|
15607
15618
|
_showTooltip(contents) {
|
|
15608
15619
|
if (!this._tooltip) {
|
|
@@ -15823,15 +15834,15 @@ class MovablePoint$4 {
|
|
|
15823
15834
|
this.movable.toFront();
|
|
15824
15835
|
}
|
|
15825
15836
|
}
|
|
15826
|
-
MovablePoint$
|
|
15827
|
-
MovablePoint$
|
|
15828
|
-
MovablePoint$
|
|
15829
|
-
MovablePoint$
|
|
15830
|
-
MovablePoint$
|
|
15831
|
-
MovablePoint$
|
|
15832
|
-
MovablePoint$
|
|
15833
|
-
MovablePoint$
|
|
15834
|
-
MovablePoint$
|
|
15837
|
+
MovablePoint$5.add = MovablePointOptions.add;
|
|
15838
|
+
MovablePoint$5.modify = MovablePointOptions.modify;
|
|
15839
|
+
MovablePoint$5.draw = MovablePointOptions.draw;
|
|
15840
|
+
MovablePoint$5.remove = MovablePointOptions.remove;
|
|
15841
|
+
MovablePoint$5.onMoveStart = MovablePointOptions.onMoveStart;
|
|
15842
|
+
MovablePoint$5.constraints = MovablePointOptions.constraints;
|
|
15843
|
+
MovablePoint$5.onMove = MovablePointOptions.onMove;
|
|
15844
|
+
MovablePoint$5.onMoveEnd = MovablePointOptions.onMoveEnd;
|
|
15845
|
+
MovablePoint$5.onClick = MovablePointOptions.onClick;
|
|
15835
15846
|
function getKey(eventName, id) {
|
|
15836
15847
|
return eventName + ":" + id;
|
|
15837
15848
|
}
|
|
@@ -16425,10 +16436,10 @@ _.extend(MovablePolygon.prototype, {
|
|
|
16425
16436
|
});
|
|
16426
16437
|
|
|
16427
16438
|
const Interactive2 = {
|
|
16428
|
-
MovablePoint: MovablePoint$
|
|
16439
|
+
MovablePoint: MovablePoint$5,
|
|
16429
16440
|
addMovablePoint: function (graphie, options) {
|
|
16430
16441
|
const movable = new Movable(graphie, {});
|
|
16431
|
-
return new MovablePoint$
|
|
16442
|
+
return new MovablePoint$5(graphie, movable, options);
|
|
16432
16443
|
},
|
|
16433
16444
|
MovableLine: MovableLine$4,
|
|
16434
16445
|
addMovableLine: function (graphie, options) {
|
|
@@ -16469,7 +16480,7 @@ const Interactive2 = {
|
|
|
16469
16480
|
}
|
|
16470
16481
|
};
|
|
16471
16482
|
|
|
16472
|
-
const MovablePoint$
|
|
16483
|
+
const MovablePoint$4 = GraphieClasses.createClass({
|
|
16473
16484
|
displayName: "MovablePoint",
|
|
16474
16485
|
movableProps: ["children"],
|
|
16475
16486
|
_getProps: function () {
|
|
@@ -16526,7 +16537,7 @@ const MovablePoint$3 = GraphieClasses.createClass({
|
|
|
16526
16537
|
});
|
|
16527
16538
|
|
|
16528
16539
|
// Include helper methods, such as MovablePoint.constrain.snap()
|
|
16529
|
-
_.extend(MovablePoint$
|
|
16540
|
+
_.extend(MovablePoint$4, Interactive2.MovablePoint);
|
|
16530
16541
|
const MovableLine$3 = GraphieClasses.createClass({
|
|
16531
16542
|
displayName: "MovableLine",
|
|
16532
16543
|
movableProps: ["children"],
|
|
@@ -16696,7 +16707,7 @@ var Movables = {
|
|
|
16696
16707
|
Label: Label$1,
|
|
16697
16708
|
Line: Line$3,
|
|
16698
16709
|
MovableLine: MovableLine$3,
|
|
16699
|
-
MovablePoint: MovablePoint$
|
|
16710
|
+
MovablePoint: MovablePoint$4,
|
|
16700
16711
|
Parabola: Parabola,
|
|
16701
16712
|
Path: Path,
|
|
16702
16713
|
Plot: Plot$2,
|
|
@@ -17025,17 +17036,15 @@ class ImageLoader extends React.Component {
|
|
|
17025
17036
|
src,
|
|
17026
17037
|
imgProps
|
|
17027
17038
|
} = this.props;
|
|
17028
|
-
let onKeyUp
|
|
17029
|
-
let onKeyDown
|
|
17039
|
+
let onKeyUp;
|
|
17040
|
+
let onKeyDown;
|
|
17030
17041
|
if (imgProps.onClick != null) {
|
|
17031
|
-
// @ts-expect-error - TS2322 - Type '(e: React.KeyboardEvent) => void' is not assignable to type 'null'.
|
|
17032
17042
|
onKeyUp = e => {
|
|
17033
17043
|
// 13 is enter key, 32 is space key
|
|
17034
17044
|
if (e.keyCode === 13 || e.keyCode === 32) {
|
|
17035
17045
|
imgProps.onClick && imgProps.onClick(e);
|
|
17036
17046
|
}
|
|
17037
17047
|
};
|
|
17038
|
-
// @ts-expect-error - TS2322 - Type '(e: React.KeyboardEvent) => void' is not assignable to type 'null'.
|
|
17039
17048
|
onKeyDown = e => {
|
|
17040
17049
|
// 32 is space key
|
|
17041
17050
|
if (e.keyCode === 32) {
|
|
@@ -17046,12 +17055,8 @@ class ImageLoader extends React.Component {
|
|
|
17046
17055
|
}
|
|
17047
17056
|
const staticUrl = getDependencies().staticUrl;
|
|
17048
17057
|
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
|
-
,
|
|
17058
|
+
src: staticUrl(src),
|
|
17059
|
+
onKeyUp: onKeyUp,
|
|
17055
17060
|
onKeyDown: onKeyDown
|
|
17056
17061
|
}, imgProps));
|
|
17057
17062
|
};
|
|
@@ -17549,18 +17554,14 @@ class SvgImage extends React.Component {
|
|
|
17549
17554
|
allowFullBleed: this.props.allowFullBleed && isImageProbablyPhotograph(imageSrc)
|
|
17550
17555
|
}, /*#__PURE__*/React.createElement(ImageLoader, {
|
|
17551
17556
|
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
|
-
,
|
|
17557
|
+
imgProps: imageProps,
|
|
17555
17558
|
preloader: preloader,
|
|
17556
17559
|
onUpdate: this.handleUpdate
|
|
17557
17560
|
}), extraGraphie);
|
|
17558
17561
|
}
|
|
17559
17562
|
imageProps.style = dimensions;
|
|
17560
17563
|
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
|
-
,
|
|
17564
|
+
src: imageSrc,
|
|
17564
17565
|
preloader: preloader,
|
|
17565
17566
|
imgProps: imageProps,
|
|
17566
17567
|
onUpdate: this.handleUpdate
|
|
@@ -17610,9 +17611,7 @@ class SvgImage extends React.Component {
|
|
|
17610
17611
|
}, /*#__PURE__*/React.createElement(ImageLoader, {
|
|
17611
17612
|
src: imageUrl,
|
|
17612
17613
|
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
|
-
,
|
|
17614
|
+
onUpdate: this.handleUpdate,
|
|
17616
17615
|
preloader: preloader,
|
|
17617
17616
|
imgProps: imageProps
|
|
17618
17617
|
}), graphie, extraGraphie);
|
|
@@ -17624,9 +17623,7 @@ class SvgImage extends React.Component {
|
|
|
17624
17623
|
}, /*#__PURE__*/React.createElement(ImageLoader, {
|
|
17625
17624
|
src: imageUrl,
|
|
17626
17625
|
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
|
-
,
|
|
17626
|
+
onUpdate: this.handleUpdate,
|
|
17630
17627
|
preloader: preloader,
|
|
17631
17628
|
imgProps: imageProps
|
|
17632
17629
|
}), graphie);
|
|
@@ -18199,33 +18196,33 @@ class Lint extends React.Component {
|
|
|
18199
18196
|
let warningText;
|
|
18200
18197
|
let warningTextStyle;
|
|
18201
18198
|
if (this.props.severity === Severity.Error) {
|
|
18202
|
-
severityStyle = styles$
|
|
18199
|
+
severityStyle = styles$B.indicatorError;
|
|
18203
18200
|
warningText = "Error";
|
|
18204
|
-
warningTextStyle = styles$
|
|
18201
|
+
warningTextStyle = styles$B.publishBlockingError;
|
|
18205
18202
|
} else if (this.props.severity === Severity.Warning) {
|
|
18206
|
-
severityStyle = styles$
|
|
18203
|
+
severityStyle = styles$B.indicatorWarning;
|
|
18207
18204
|
warningText = "Warning";
|
|
18208
|
-
warningTextStyle = styles$
|
|
18205
|
+
warningTextStyle = styles$B.warning;
|
|
18209
18206
|
} else {
|
|
18210
|
-
severityStyle = styles$
|
|
18207
|
+
severityStyle = styles$B.indicatorGuideline;
|
|
18211
18208
|
warningText = "Recommendation";
|
|
18212
|
-
warningTextStyle = styles$
|
|
18209
|
+
warningTextStyle = styles$B.warning;
|
|
18213
18210
|
}
|
|
18214
18211
|
return /*#__PURE__*/React.createElement("a", {
|
|
18215
18212
|
href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
|
|
18216
18213
|
target: "lint-help-window",
|
|
18217
18214
|
className: css(style)
|
|
18218
18215
|
}, /*#__PURE__*/React.createElement("span", {
|
|
18219
|
-
className: css(styles$
|
|
18216
|
+
className: css(styles$B.indicator, severityStyle)
|
|
18220
18217
|
}, this.props.severity === 1 && /*#__PURE__*/React.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React.createElement("div", {
|
|
18221
|
-
className: css(styles$
|
|
18218
|
+
className: css(styles$B.tooltip, tooltipAbove && styles$B.tooltipAbove)
|
|
18222
18219
|
}, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React.createElement("p", {
|
|
18223
18220
|
key: i,
|
|
18224
|
-
className: css(styles$
|
|
18221
|
+
className: css(styles$B.tooltipParagraph)
|
|
18225
18222
|
}, /*#__PURE__*/React.createElement("span", {
|
|
18226
18223
|
className: css(warningTextStyle)
|
|
18227
18224
|
}, warningText, ":", " "), m)), /*#__PURE__*/React.createElement("div", {
|
|
18228
|
-
className: css(styles$
|
|
18225
|
+
className: css(styles$B.tail, tooltipAbove && styles$B.tailAbove)
|
|
18229
18226
|
})));
|
|
18230
18227
|
};
|
|
18231
18228
|
}
|
|
@@ -18263,20 +18260,20 @@ class Lint extends React.Component {
|
|
|
18263
18260
|
}
|
|
18264
18261
|
if (blockHighlight) {
|
|
18265
18262
|
return /*#__PURE__*/React.createElement("span", {
|
|
18266
|
-
className: css(styles$
|
|
18267
|
-
}, this.renderLink(styles$
|
|
18263
|
+
className: css(styles$B.lintContainer, styles$B.lintContainerBlock)
|
|
18264
|
+
}, this.renderLink(styles$B.radioWidgetHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
|
|
18268
18265
|
}
|
|
18269
18266
|
if (inline) {
|
|
18270
18267
|
return /*#__PURE__*/React.createElement("span", {
|
|
18271
|
-
className: css(styles$
|
|
18272
|
-
}, this.renderLink(styles$
|
|
18268
|
+
className: css(styles$B.lintContainer)
|
|
18269
|
+
}, this.renderLink(styles$B.inlineHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
|
|
18273
18270
|
}
|
|
18274
18271
|
return /*#__PURE__*/React.createElement("div", {
|
|
18275
|
-
className: css(styles$
|
|
18276
|
-
}, this.renderLink(styles$
|
|
18272
|
+
className: css(styles$B.lintContainer)
|
|
18273
|
+
}, this.renderLink(styles$B.hoverTarget), /*#__PURE__*/React.createElement("div", null, children));
|
|
18277
18274
|
}
|
|
18278
18275
|
}
|
|
18279
|
-
const styles$
|
|
18276
|
+
const styles$B = StyleSheet.create({
|
|
18280
18277
|
// This is the class of the outermost element.
|
|
18281
18278
|
// We use relative positioning so that the lint indicator can be
|
|
18282
18279
|
// positioned absolutely relative to the position of the linty container.
|
|
@@ -18953,15 +18950,17 @@ class TranslationLinter {
|
|
|
18953
18950
|
}
|
|
18954
18951
|
|
|
18955
18952
|
/**
|
|
18956
|
-
* Preprocess TeX code to convert things that
|
|
18953
|
+
* Preprocess TeX code to convert things that MathJax doesn't know how to handle
|
|
18957
18954
|
* to things is does.
|
|
18958
18955
|
*/
|
|
18959
|
-
|
|
18960
18956
|
var preprocessTex = (texCode => texCode
|
|
18961
18957
|
// Replace uses of \begin{align}...\end{align} which KaTeX doesn't
|
|
18962
18958
|
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
18963
18959
|
// the same is supported by KaTeX. It does the same for align*.
|
|
18964
18960
|
// TODO(kevinb) update content to use aligned instead of align.
|
|
18961
|
+
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
18962
|
+
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
18963
|
+
// "aligned").
|
|
18965
18964
|
.replace(/\{align[*]?\}/g, "{aligned}")
|
|
18966
18965
|
// Replace non-breaking spaces with regular spaces.
|
|
18967
18966
|
.replace(/[\u00a0]/g, " "));
|
|
@@ -20211,7 +20210,7 @@ class Renderer extends React.Component {
|
|
|
20211
20210
|
paddingLeft: margin,
|
|
20212
20211
|
paddingRight: margin
|
|
20213
20212
|
};
|
|
20214
|
-
const mobileInnerStyle = _extends({}, innerStyle, styles$
|
|
20213
|
+
const mobileInnerStyle = _extends({}, innerStyle, styles$A.mobileZoomableParentFix);
|
|
20215
20214
|
return /*#__PURE__*/React.createElement("div", {
|
|
20216
20215
|
key: state.key,
|
|
20217
20216
|
className: "perseus-block-math",
|
|
@@ -20238,6 +20237,9 @@ class Renderer extends React.Component {
|
|
|
20238
20237
|
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
20239
20238
|
// the same is supported by KaTeX. It does the same for align*.
|
|
20240
20239
|
// TODO(kevinb) update content to use aligned instead of align.
|
|
20240
|
+
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
20241
|
+
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
20242
|
+
// "aligned").
|
|
20241
20243
|
const tex = node.content.replace(/\{align[*]?\}/g, "{aligned}");
|
|
20242
20244
|
|
|
20243
20245
|
// We render math here instead of in perseus-markdown.jsx
|
|
@@ -20332,7 +20334,7 @@ class Renderer extends React.Component {
|
|
|
20332
20334
|
paddingLeft: 0,
|
|
20333
20335
|
paddingRight: 0
|
|
20334
20336
|
};
|
|
20335
|
-
const mobileInnerStyle = _extends({}, innerStyle, styles$
|
|
20337
|
+
const mobileInnerStyle = _extends({}, innerStyle, styles$A.mobileZoomableParentFix);
|
|
20336
20338
|
const wrappedOutput = /*#__PURE__*/React.createElement("div", {
|
|
20337
20339
|
style: _extends({}, mobileInnerStyle, {
|
|
20338
20340
|
overflowX: "auto"
|
|
@@ -20981,7 +20983,7 @@ Renderer.defaultProps = {
|
|
|
20981
20983
|
onSerializedStateUpdated: () => {},
|
|
20982
20984
|
linterContext: PerseusLinter.linterContextDefault
|
|
20983
20985
|
};
|
|
20984
|
-
const styles$
|
|
20986
|
+
const styles$A = {
|
|
20985
20987
|
mobileZoomableParentFix: {
|
|
20986
20988
|
// NOTE(abdul): There is an issue where transform animations will
|
|
20987
20989
|
// cause the Zoomable component to disappear when running on the
|
|
@@ -21052,28 +21054,24 @@ class TextInput extends React.Component {
|
|
|
21052
21054
|
style
|
|
21053
21055
|
} = this.props;
|
|
21054
21056
|
const formattedValue = value === null ? "" : value.toString();
|
|
21055
|
-
return (
|
|
21056
|
-
|
|
21057
|
-
|
|
21058
|
-
|
|
21059
|
-
|
|
21060
|
-
|
|
21061
|
-
|
|
21062
|
-
|
|
21063
|
-
|
|
21064
|
-
|
|
21065
|
-
|
|
21066
|
-
|
|
21067
|
-
|
|
21068
|
-
|
|
21069
|
-
|
|
21070
|
-
|
|
21071
|
-
|
|
21072
|
-
|
|
21073
|
-
autoCapitalize: "off",
|
|
21074
|
-
autoComplete: "off"
|
|
21075
|
-
})
|
|
21076
|
-
);
|
|
21057
|
+
return /*#__PURE__*/React.createElement(TextField, {
|
|
21058
|
+
style: style,
|
|
21059
|
+
disabled: disabled,
|
|
21060
|
+
id: this.id,
|
|
21061
|
+
value: formattedValue,
|
|
21062
|
+
type: "text",
|
|
21063
|
+
"aria-label": labelText,
|
|
21064
|
+
onChange: value => this.props.onChange(value),
|
|
21065
|
+
placeholder: placeholder,
|
|
21066
|
+
onFocus: onFocus,
|
|
21067
|
+
onBlur: onBlur,
|
|
21068
|
+
onKeyDown: onKeyDown
|
|
21069
|
+
// @ts-expect-error - TS2322 - Type '{ style: StyleType; disabled: boolean | undefined; id: string; value: string; type: "text"; "aria-label": string | undefined; onChange: (value: string) => void; placeholder: string | undefined; ... 5 more ...; autoComplete: string; }' is not assignable to type 'IntrinsicAttributes & ExportProps & RefAttributes<HTMLInputElement>'.
|
|
21070
|
+
,
|
|
21071
|
+
autoCorrect: "off",
|
|
21072
|
+
autoCapitalize: "off",
|
|
21073
|
+
autoComplete: "off"
|
|
21074
|
+
});
|
|
21077
21075
|
}
|
|
21078
21076
|
}
|
|
21079
21077
|
TextInput.defaultProps = {
|
|
@@ -21855,10 +21853,10 @@ class InputNumber extends React.Component {
|
|
|
21855
21853
|
// Note: This is _very_ similar to what `numeric-input.jsx` does. If
|
|
21856
21854
|
// you modify this, double-check if you also need to modify that
|
|
21857
21855
|
// component.
|
|
21858
|
-
const inputStyles = [styles$
|
|
21856
|
+
const inputStyles = [styles$z.default, this.props.size === "small" ? styles$z.small : null, this.props.rightAlign ? styles$z.rightAlign : styles$z.leftAlign];
|
|
21859
21857
|
// Unanswered
|
|
21860
21858
|
if (rubric && !this.props.currentValue) {
|
|
21861
|
-
inputStyles.push(styles$
|
|
21859
|
+
inputStyles.push(styles$z.answerStateUnanswered);
|
|
21862
21860
|
}
|
|
21863
21861
|
return /*#__PURE__*/React.createElement(InputWithExamples
|
|
21864
21862
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -21943,7 +21941,7 @@ InputNumber.defaultProps = {
|
|
|
21943
21941
|
apiOptions: ApiOptions.defaults,
|
|
21944
21942
|
linterContext: linterContextDefault
|
|
21945
21943
|
};
|
|
21946
|
-
const styles$
|
|
21944
|
+
const styles$z = StyleSheet.create({
|
|
21947
21945
|
default: {
|
|
21948
21946
|
width: 80,
|
|
21949
21947
|
height: "auto"
|
|
@@ -22938,7 +22936,7 @@ const FocusRing = function FocusRing(props) {
|
|
|
22938
22936
|
};
|
|
22939
22937
|
return /*#__PURE__*/React.createElement("span", {
|
|
22940
22938
|
"data-testid": "focus-ring",
|
|
22941
|
-
className: css(styles$
|
|
22939
|
+
className: css(styles$y.ring),
|
|
22942
22940
|
style: style
|
|
22943
22941
|
}, children);
|
|
22944
22942
|
};
|
|
@@ -22947,7 +22945,7 @@ FocusRing.defaultProps = {
|
|
|
22947
22945
|
color: kaGreen$1,
|
|
22948
22946
|
multipleSelect: false
|
|
22949
22947
|
};
|
|
22950
|
-
const styles$
|
|
22948
|
+
const styles$y = StyleSheet.create({
|
|
22951
22949
|
ring: {
|
|
22952
22950
|
margin: "auto",
|
|
22953
22951
|
display: "inline-block",
|
|
@@ -22974,7 +22972,7 @@ function getChoiceLetter(pos, strings) {
|
|
|
22974
22972
|
}
|
|
22975
22973
|
|
|
22976
22974
|
const CHOICE_ICON_SIZE = 24;
|
|
22977
|
-
const styles$
|
|
22975
|
+
const styles$x = StyleSheet.create({
|
|
22978
22976
|
iconWrapper: {
|
|
22979
22977
|
display: "inline-block",
|
|
22980
22978
|
position: "relative"
|
|
@@ -22997,7 +22995,7 @@ const CrossOutLine = function CrossOutLine(props) {
|
|
|
22997
22995
|
width: CROSS_OUT_LINE_SIZE,
|
|
22998
22996
|
height: CROSS_OUT_LINE_SIZE,
|
|
22999
22997
|
viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
|
|
23000
|
-
className: css(styles$
|
|
22998
|
+
className: css(styles$w.crossOutLine),
|
|
23001
22999
|
"data-testid": "choice-icon__cross-out-line"
|
|
23002
23000
|
}, /*#__PURE__*/React.createElement("line", {
|
|
23003
23001
|
// The line stretches from the bottom-left to top-right.
|
|
@@ -23012,7 +23010,7 @@ const CrossOutLine = function CrossOutLine(props) {
|
|
|
23012
23010
|
strokeLinecap: "round"
|
|
23013
23011
|
}));
|
|
23014
23012
|
};
|
|
23015
|
-
const styles$
|
|
23013
|
+
const styles$w = StyleSheet.create({
|
|
23016
23014
|
crossOutLine: {
|
|
23017
23015
|
// Center the icon within the container.
|
|
23018
23016
|
position: "absolute",
|
|
@@ -23096,7 +23094,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
23096
23094
|
} = props;
|
|
23097
23095
|
const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
|
|
23098
23096
|
return /*#__PURE__*/React.createElement("div", {
|
|
23099
|
-
className: css(styles$
|
|
23097
|
+
className: css(styles$x.iconWrapper)
|
|
23100
23098
|
}, /*#__PURE__*/React.createElement(FocusRing, {
|
|
23101
23099
|
color: color.blue,
|
|
23102
23100
|
visible: focused || hovered,
|
|
@@ -23105,13 +23103,13 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
23105
23103
|
// @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
23104
|
style: dynamicStyles,
|
|
23107
23105
|
"data-testid": "choice-icon__library-choice-icon",
|
|
23108
|
-
className: css(styles$
|
|
23106
|
+
className: css(styles$v.circle, showCorrectness && correct && styles$v.circleCorrect, showCorrectness && !correct && styles$v.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$v.circleIncorrectAnswered)
|
|
23109
23107
|
// used in BaseRadio editMode to check
|
|
23110
23108
|
// if we actually clicked on the radio icon
|
|
23111
23109
|
,
|
|
23112
23110
|
"data-is-radio-icon": true
|
|
23113
23111
|
}, /*#__PURE__*/React.createElement("div", {
|
|
23114
|
-
className: css(styles$
|
|
23112
|
+
className: css(styles$v.innerWrapper)
|
|
23115
23113
|
}, /*#__PURE__*/React.createElement(ChoiceInner, {
|
|
23116
23114
|
pos: pos,
|
|
23117
23115
|
showCorrectness: showCorrectness,
|
|
@@ -23120,7 +23118,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
23120
23118
|
color: dynamicStyles.borderColor
|
|
23121
23119
|
}));
|
|
23122
23120
|
};
|
|
23123
|
-
const styles$
|
|
23121
|
+
const styles$v = StyleSheet.create({
|
|
23124
23122
|
innerWrapper: {
|
|
23125
23123
|
width: CHOICE_ICON_SIZE,
|
|
23126
23124
|
height: CHOICE_ICON_SIZE,
|
|
@@ -23215,19 +23213,19 @@ const OptionStatus = function OptionStatus(props) {
|
|
|
23215
23213
|
}
|
|
23216
23214
|
let textStyle;
|
|
23217
23215
|
if (correct) {
|
|
23218
|
-
textStyle = styles$
|
|
23216
|
+
textStyle = styles$u.correct;
|
|
23219
23217
|
} else {
|
|
23220
23218
|
if (checked || previouslyAnswered) {
|
|
23221
|
-
textStyle = styles$
|
|
23219
|
+
textStyle = styles$u.incorrectAnswered;
|
|
23222
23220
|
} else {
|
|
23223
|
-
textStyle = styles$
|
|
23221
|
+
textStyle = styles$u.incorrect;
|
|
23224
23222
|
}
|
|
23225
23223
|
}
|
|
23226
23224
|
return /*#__PURE__*/React.createElement("div", {
|
|
23227
|
-
className: css(styles$
|
|
23225
|
+
className: css(styles$u.text, textStyle)
|
|
23228
23226
|
}, renderText(checked, correct, crossedOut, strings));
|
|
23229
23227
|
};
|
|
23230
|
-
const styles$
|
|
23228
|
+
const styles$u = StyleSheet.create({
|
|
23231
23229
|
text: {
|
|
23232
23230
|
alignItems: "center",
|
|
23233
23231
|
display: "flex",
|
|
@@ -23297,8 +23295,8 @@ const Choice = function Choice(props) {
|
|
|
23297
23295
|
crossedOut: updatedCrossedOut
|
|
23298
23296
|
});
|
|
23299
23297
|
}
|
|
23300
|
-
const descriptionClassName = classNames("description", css(styles$
|
|
23301
|
-
const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$
|
|
23298
|
+
const descriptionClassName = classNames("description", css(styles$t.description));
|
|
23299
|
+
const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$t.rationale));
|
|
23302
23300
|
|
|
23303
23301
|
// We want to show the choices as dimmed out when the choices are disabled.
|
|
23304
23302
|
// However, we don't want to do this when we're in review mode in the
|
|
@@ -23458,7 +23456,7 @@ const Choice = function Choice(props) {
|
|
|
23458
23456
|
"data-testid": `perseus-radio-rationale-content-${pos}`
|
|
23459
23457
|
}, rationale));
|
|
23460
23458
|
};
|
|
23461
|
-
const styles$
|
|
23459
|
+
const styles$t = StyleSheet.create({
|
|
23462
23460
|
description: {
|
|
23463
23461
|
display: "inline-block",
|
|
23464
23462
|
width: "100%"
|
|
@@ -23657,10 +23655,10 @@ const BaseRadio = function BaseRadio(props) {
|
|
|
23657
23655
|
const isMobile = apiOptions.isMobile;
|
|
23658
23656
|
const firstChoiceHighlighted = choices[0].highlighted;
|
|
23659
23657
|
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$
|
|
23658
|
+
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));
|
|
23659
|
+
const instructionsClassName = classNames("instructions", css(styles$s.instructions, isMobile && styles$s.instructionsMobile));
|
|
23662
23660
|
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect, strings);
|
|
23663
|
-
const responsiveClassName = css(styles$
|
|
23661
|
+
const responsiveClassName = css(styles$s.responsiveFieldset);
|
|
23664
23662
|
const fieldset = /*#__PURE__*/React.createElement("fieldset", {
|
|
23665
23663
|
className: `perseus-widget-radio-fieldset ${responsiveClassName}`
|
|
23666
23664
|
}, /*#__PURE__*/React.createElement("legend", {
|
|
@@ -23711,7 +23709,7 @@ const BaseRadio = function BaseRadio(props) {
|
|
|
23711
23709
|
const aphroditeClassName = checked => {
|
|
23712
23710
|
// Whether or not to show correctness borders
|
|
23713
23711
|
// for this choice and the next choice.
|
|
23714
|
-
return css(sharedStyles.aboveScratchpad, styles$
|
|
23712
|
+
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
23713
|
};
|
|
23716
23714
|
|
|
23717
23715
|
// HACK(abdulrahman): Preloads the selection-state
|
|
@@ -23785,14 +23783,14 @@ const BaseRadio = function BaseRadio(props) {
|
|
|
23785
23783
|
// Allow for horizontal scrolling if content is too wide, which may be
|
|
23786
23784
|
// an issue especially on phones.
|
|
23787
23785
|
return /*#__PURE__*/React.createElement("div", {
|
|
23788
|
-
className: css(styles$
|
|
23786
|
+
className: css(styles$s.responsiveContainer)
|
|
23789
23787
|
}, fieldset);
|
|
23790
23788
|
};
|
|
23791
23789
|
BaseRadio.defaultProps = {
|
|
23792
23790
|
editMode: false,
|
|
23793
23791
|
multipleSelect: false
|
|
23794
23792
|
};
|
|
23795
|
-
const styles$
|
|
23793
|
+
const styles$s = StyleSheet.create({
|
|
23796
23794
|
instructions: {
|
|
23797
23795
|
display: "block",
|
|
23798
23796
|
color: gray17,
|
|
@@ -24454,9 +24452,9 @@ class Categorizer extends React.Component {
|
|
|
24454
24452
|
indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
|
|
24455
24453
|
}
|
|
24456
24454
|
const table = /*#__PURE__*/React.createElement("table", {
|
|
24457
|
-
className: "categorizer-table " + css(styles$
|
|
24455
|
+
className: "categorizer-table " + css(styles$r.mobileTable)
|
|
24458
24456
|
}, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
|
|
24459
|
-
className: css(styles$
|
|
24457
|
+
className: css(styles$r.emptyHeaderCell)
|
|
24460
24458
|
}), this.props.categories.map((category, i) => {
|
|
24461
24459
|
// Array index is the correct key here, as that's
|
|
24462
24460
|
// how category grading actually works -- no way
|
|
@@ -24464,7 +24462,7 @@ class Categorizer extends React.Component {
|
|
|
24464
24462
|
// middle. (If we later add that, this should be
|
|
24465
24463
|
// fixed.)
|
|
24466
24464
|
return /*#__PURE__*/React.createElement("th", {
|
|
24467
|
-
className: css(styles$
|
|
24465
|
+
className: css(styles$r.header),
|
|
24468
24466
|
key: i
|
|
24469
24467
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
24470
24468
|
content: category,
|
|
@@ -24486,7 +24484,7 @@ class Categorizer extends React.Component {
|
|
|
24486
24484
|
})), self.props.categories.map((catName, catNum) => {
|
|
24487
24485
|
const selected = self.props.values[itemNum] === catNum;
|
|
24488
24486
|
return /*#__PURE__*/React.createElement("td", {
|
|
24489
|
-
className: "category " + css(styles$
|
|
24487
|
+
className: "category " + css(styles$r.cell),
|
|
24490
24488
|
key: catNum
|
|
24491
24489
|
}, /*#__PURE__*/React.createElement("div", {
|
|
24492
24490
|
className: ClassNames.INTERACTIVE,
|
|
@@ -24501,7 +24499,7 @@ class Categorizer extends React.Component {
|
|
|
24501
24499
|
onChange: () => this.onChange(itemNum, catNum),
|
|
24502
24500
|
onClick: e => e.stopPropagation()
|
|
24503
24501
|
}), !isMobile && /*#__PURE__*/React.createElement("span", {
|
|
24504
|
-
className: css(styles$
|
|
24502
|
+
className: css(styles$r.radioSpan, selected && styles$r.checkedRadioSpan, this.props.static && selected && styles$r.staticCheckedRadioSpan)
|
|
24505
24503
|
}, selected ? /*#__PURE__*/React.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React.createElement(InlineIcon, iconCircleThin))));
|
|
24506
24504
|
}));
|
|
24507
24505
|
/* eslint-enable max-len */
|
|
@@ -24513,7 +24511,7 @@ class Categorizer extends React.Component {
|
|
|
24513
24511
|
"categorizer-container": true,
|
|
24514
24512
|
"static-mode": this.props.static
|
|
24515
24513
|
});
|
|
24516
|
-
const inlineStyles = this.props.apiOptions.isMobile ? [styles$
|
|
24514
|
+
const inlineStyles = this.props.apiOptions.isMobile ? [styles$r.fullBleedContainer] : [];
|
|
24517
24515
|
return /*#__PURE__*/React.createElement("div", {
|
|
24518
24516
|
className: extraClassNames + " " + css(...inlineStyles)
|
|
24519
24517
|
}, table);
|
|
@@ -24566,7 +24564,7 @@ const pageMargin = 16;
|
|
|
24566
24564
|
|
|
24567
24565
|
// Stylesheets aren't directly testable
|
|
24568
24566
|
/* c8 ignore next */
|
|
24569
|
-
const styles$
|
|
24567
|
+
const styles$r = StyleSheet.create({
|
|
24570
24568
|
mobileTable: {
|
|
24571
24569
|
[mediaQueries.smOrSmaller]: {
|
|
24572
24570
|
minWidth: "auto"
|
|
@@ -24802,7 +24800,7 @@ class CSProgram extends React.Component {
|
|
|
24802
24800
|
// creator "went wild".
|
|
24803
24801
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
24804
24802
|
return /*#__PURE__*/React.createElement("div", {
|
|
24805
|
-
className: css(styles$
|
|
24803
|
+
className: css(styles$q.widthOverride, styleContainer && styles$q.container)
|
|
24806
24804
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
24807
24805
|
sandbox: sandboxOptions,
|
|
24808
24806
|
src: url,
|
|
@@ -24831,7 +24829,7 @@ CSProgram.defaultProps = {
|
|
|
24831
24829
|
// optional message
|
|
24832
24830
|
message: null
|
|
24833
24831
|
};
|
|
24834
|
-
const styles$
|
|
24832
|
+
const styles$q = StyleSheet.create({
|
|
24835
24833
|
// Override the inherited width from the perseus paragraph class
|
|
24836
24834
|
// 820 is minimum width for 420px editor and 400px canvas
|
|
24837
24835
|
widthOverride: {
|
|
@@ -24874,7 +24872,7 @@ class Definition extends React.Component {
|
|
|
24874
24872
|
}) => /*#__PURE__*/React.createElement(Popover, {
|
|
24875
24873
|
content: /*#__PURE__*/React.createElement(PopoverContentCore, {
|
|
24876
24874
|
color: "white",
|
|
24877
|
-
style: styles$
|
|
24875
|
+
style: styles$p.tooltipBody,
|
|
24878
24876
|
closeButtonVisible: true
|
|
24879
24877
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
24880
24878
|
apiOptions: this.props.apiOptions,
|
|
@@ -24907,7 +24905,7 @@ Definition.defaultProps = {
|
|
|
24907
24905
|
togglePrompt: "define me",
|
|
24908
24906
|
definition: "definition goes here"
|
|
24909
24907
|
};
|
|
24910
|
-
const styles$
|
|
24908
|
+
const styles$p = {
|
|
24911
24909
|
tooltipBody: {
|
|
24912
24910
|
color: color.offBlack,
|
|
24913
24911
|
fontSize: 20,
|
|
@@ -25135,7 +25133,7 @@ class Explanation extends React.Component {
|
|
|
25135
25133
|
marginRight: "-6px",
|
|
25136
25134
|
"white-space": "normal"
|
|
25137
25135
|
};
|
|
25138
|
-
const contentStyling = [styles$
|
|
25136
|
+
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
25137
|
return /*#__PURE__*/React.createElement(UniqueIDProvider, {
|
|
25140
25138
|
mockOnFirstRender: true,
|
|
25141
25139
|
scope: "explanation-widget"
|
|
@@ -25154,7 +25152,7 @@ class Explanation extends React.Component {
|
|
|
25154
25152
|
"aria-hidden": !this.state.expanded,
|
|
25155
25153
|
testId: "content-container"
|
|
25156
25154
|
}, /*#__PURE__*/React.createElement(View, {
|
|
25157
|
-
style: styles$
|
|
25155
|
+
style: styles$o.contentWrapper
|
|
25158
25156
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
25159
25157
|
apiOptions: this.props.apiOptions,
|
|
25160
25158
|
content: this.props.explanation,
|
|
@@ -25175,7 +25173,7 @@ Explanation.defaultProps = {
|
|
|
25175
25173
|
const leftBorderSpacing = 23;
|
|
25176
25174
|
const verticalContentPadding = 10;
|
|
25177
25175
|
const arrowHeight = 14;
|
|
25178
|
-
const styles$
|
|
25176
|
+
const styles$o = StyleSheet.create({
|
|
25179
25177
|
content: {
|
|
25180
25178
|
borderLeft: "0px solid #ccc",
|
|
25181
25179
|
display: "inline-grid",
|
|
@@ -25239,15 +25237,15 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
25239
25237
|
correctExcited,
|
|
25240
25238
|
nextQuestion
|
|
25241
25239
|
} = this.context.strings;
|
|
25242
|
-
const answerBarStyle = _extends({}, styles$
|
|
25240
|
+
const answerBarStyle = _extends({}, styles$n.answerBar, {
|
|
25243
25241
|
backgroundColor: answerBarState === "CORRECT" ? color.offWhite : "white",
|
|
25244
25242
|
// Center the "Correct!" message only when there's no next question
|
|
25245
25243
|
justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
|
|
25246
25244
|
});
|
|
25247
25245
|
const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React.createElement("span", {
|
|
25248
|
-
style: styles$
|
|
25246
|
+
style: styles$n.text
|
|
25249
25247
|
}, /*#__PURE__*/React.createElement("span", {
|
|
25250
|
-
style: styles$
|
|
25248
|
+
style: styles$n.tryAgainIcon
|
|
25251
25249
|
}, /*#__PURE__*/React.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React.createElement("span", {
|
|
25252
25250
|
style: {
|
|
25253
25251
|
marginLeft: 8
|
|
@@ -25266,7 +25264,7 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
25266
25264
|
return /*#__PURE__*/React.createElement("div", {
|
|
25267
25265
|
style: answerBarStyle
|
|
25268
25266
|
}, /*#__PURE__*/React.createElement("span", {
|
|
25269
|
-
style: styles$
|
|
25267
|
+
style: styles$n.text
|
|
25270
25268
|
}, /*#__PURE__*/React.createElement("span", {
|
|
25271
25269
|
style: {
|
|
25272
25270
|
fontSize: 28,
|
|
@@ -25289,7 +25287,7 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
25289
25287
|
}
|
|
25290
25288
|
GradedGroupAnswerBar.contextType = PerseusI18nContext;
|
|
25291
25289
|
const fontSize = 17;
|
|
25292
|
-
const styles$
|
|
25290
|
+
const styles$n = {
|
|
25293
25291
|
answerBar: {
|
|
25294
25292
|
display: "flex",
|
|
25295
25293
|
alignItems: "center",
|
|
@@ -25474,7 +25472,7 @@ class GradedGroup extends React.Component {
|
|
|
25474
25472
|
}));
|
|
25475
25473
|
gradeStatus = this.context.strings.incorrect;
|
|
25476
25474
|
}
|
|
25477
|
-
const mobileClass = this.props.inGradedGroupSet ? css(styles$
|
|
25475
|
+
const mobileClass = this.props.inGradedGroupSet ? css(styles$m.gradedGroupInSet) : css(styles$m.gradedGroup);
|
|
25478
25476
|
const classes = classNames({
|
|
25479
25477
|
[mobileClass]: apiOptions.isMobile,
|
|
25480
25478
|
"perseus-graded-group": true,
|
|
@@ -25493,7 +25491,7 @@ class GradedGroup extends React.Component {
|
|
|
25493
25491
|
return /*#__PURE__*/React.createElement("div", {
|
|
25494
25492
|
className: classes
|
|
25495
25493
|
}, !!this.props.title && /*#__PURE__*/React.createElement("div", {
|
|
25496
|
-
className: css(styles$
|
|
25494
|
+
className: css(styles$m.title)
|
|
25497
25495
|
}, this.props.title), /*#__PURE__*/React.createElement(Renderer, _extends({}, this.props, {
|
|
25498
25496
|
// eslint-disable-next-line react/no-string-refs
|
|
25499
25497
|
ref: "renderer",
|
|
@@ -25526,7 +25524,7 @@ class GradedGroup extends React.Component {
|
|
|
25526
25524
|
}, this.context.strings.nextQuestion), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
|
|
25527
25525
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
25528
25526
|
tabIndex: "0",
|
|
25529
|
-
className: css(styles$
|
|
25527
|
+
className: css(styles$m.explanationTitle),
|
|
25530
25528
|
onClick: () => this.setState({
|
|
25531
25529
|
showHint: false
|
|
25532
25530
|
}),
|
|
@@ -25559,7 +25557,7 @@ class GradedGroup extends React.Component {
|
|
|
25559
25557
|
showHint: true
|
|
25560
25558
|
});
|
|
25561
25559
|
},
|
|
25562
|
-
className: css(styles$
|
|
25560
|
+
className: css(styles$m.showHintLink)
|
|
25563
25561
|
}, this.context.strings.explain)), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React.createElement(GradedGroupAnswerBar, {
|
|
25564
25562
|
apiOptions: apiOptions,
|
|
25565
25563
|
answerBarState: answerBarState,
|
|
@@ -25581,7 +25579,7 @@ GradedGroup.defaultProps = {
|
|
|
25581
25579
|
const traverseChildWidgets$2 = function traverseChildWidgets(props, traverseRenderer) {
|
|
25582
25580
|
return _.extend({}, props, traverseRenderer(props));
|
|
25583
25581
|
};
|
|
25584
|
-
const styles$
|
|
25582
|
+
const styles$m = StyleSheet.create({
|
|
25585
25583
|
gradedGroupInSet: {
|
|
25586
25584
|
// Reset a few desktop-only styles that come from graded-group.less
|
|
25587
25585
|
marginLeft: 0,
|
|
@@ -25654,18 +25652,18 @@ class Indicators extends React.Component {
|
|
|
25654
25652
|
return /*#__PURE__*/React.createElement("ul", {
|
|
25655
25653
|
// reduntantly add class name for use in .less files--
|
|
25656
25654
|
// the styles object key gets hashed
|
|
25657
|
-
className: classNames(css(styles$
|
|
25655
|
+
className: classNames(css(styles$l.indicatorContainer), "indicatorContainer")
|
|
25658
25656
|
}, this.props.gradedGroups.map(({
|
|
25659
25657
|
title
|
|
25660
25658
|
}, i) => /*#__PURE__*/React.createElement("li", {
|
|
25661
|
-
className: css(styles$
|
|
25659
|
+
className: css(styles$l.indicator),
|
|
25662
25660
|
key: title
|
|
25663
25661
|
}, /*#__PURE__*/React.createElement(Clickable, {
|
|
25664
25662
|
role: "button",
|
|
25665
25663
|
"aria-label": this.context.strings.skipToTitle({
|
|
25666
25664
|
title
|
|
25667
25665
|
}),
|
|
25668
|
-
style: styles$
|
|
25666
|
+
style: styles$l.indicatorButton,
|
|
25669
25667
|
onClick: () => this.props.onChangeCurrentGroup(i),
|
|
25670
25668
|
onKeyDown: e => this.handleKeyDown(e, i)
|
|
25671
25669
|
}, ({
|
|
@@ -25673,9 +25671,9 @@ class Indicators extends React.Component {
|
|
|
25673
25671
|
focused,
|
|
25674
25672
|
pressed
|
|
25675
25673
|
}) => /*#__PURE__*/React.createElement(View, {
|
|
25676
|
-
style: [styles$
|
|
25674
|
+
style: [styles$l.indicatorDot, (hovered || focused || pressed) && styles$l.indicatorDotFocused]
|
|
25677
25675
|
}, i === this.props.currentGroup && /*#__PURE__*/React.createElement(View, {
|
|
25678
|
-
style: styles$
|
|
25676
|
+
style: styles$l.indicatorDotActive
|
|
25679
25677
|
}, /*#__PURE__*/React.createElement("span", {
|
|
25680
25678
|
className: css(a11y.srOnly)
|
|
25681
25679
|
}, this.context.strings.current)))))));
|
|
@@ -25739,7 +25737,7 @@ class GradedGroupSet extends React.Component {
|
|
|
25739
25737
|
} = getDependencies();
|
|
25740
25738
|
if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
|
|
25741
25739
|
return /*#__PURE__*/React.createElement("div", {
|
|
25742
|
-
className: css(styles$
|
|
25740
|
+
className: css(styles$l.container)
|
|
25743
25741
|
}, this.props.gradedGroups.map((gradedGroup, i) => {
|
|
25744
25742
|
return (
|
|
25745
25743
|
/*#__PURE__*/
|
|
@@ -25762,13 +25760,13 @@ class GradedGroupSet extends React.Component {
|
|
|
25762
25760
|
const numGroups = this.props.gradedGroups.length;
|
|
25763
25761
|
const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
|
|
25764
25762
|
return /*#__PURE__*/React.createElement("div", {
|
|
25765
|
-
className: css(styles$
|
|
25763
|
+
className: css(styles$l.container)
|
|
25766
25764
|
}, /*#__PURE__*/React.createElement("div", {
|
|
25767
|
-
className: css(styles$
|
|
25765
|
+
className: css(styles$l.top)
|
|
25768
25766
|
}, /*#__PURE__*/React.createElement("div", {
|
|
25769
|
-
className: css(styles$
|
|
25767
|
+
className: css(styles$l.title)
|
|
25770
25768
|
}, currentGroup.title), /*#__PURE__*/React.createElement("div", {
|
|
25771
|
-
className: css(styles$
|
|
25769
|
+
className: css(styles$l.spacer)
|
|
25772
25770
|
}), /*#__PURE__*/React.createElement(Indicators, {
|
|
25773
25771
|
currentGroup: this.state.currentGroup,
|
|
25774
25772
|
gradedGroups: this.props.gradedGroups,
|
|
@@ -25810,7 +25808,7 @@ var GradedGroupSet$1 = {
|
|
|
25810
25808
|
tracking: "all",
|
|
25811
25809
|
isLintable: true
|
|
25812
25810
|
};
|
|
25813
|
-
const styles$
|
|
25811
|
+
const styles$l = StyleSheet.create({
|
|
25814
25812
|
top: {
|
|
25815
25813
|
display: "flex",
|
|
25816
25814
|
flexDirection: "row"
|
|
@@ -25915,7 +25913,7 @@ class ButtonGroup extends React.Component {
|
|
|
25915
25913
|
id: "" + i,
|
|
25916
25914
|
ref: "button" + i,
|
|
25917
25915
|
key: "" + i,
|
|
25918
|
-
className: css(styles$
|
|
25916
|
+
className: css(styles$k.buttonStyle, button.value === value && styles$k.selectedStyle),
|
|
25919
25917
|
onClick: () => this.toggleSelect(button.value)
|
|
25920
25918
|
}, button.content || "" + button.value);
|
|
25921
25919
|
});
|
|
@@ -25932,7 +25930,7 @@ ButtonGroup.defaultProps = {
|
|
|
25932
25930
|
value: null,
|
|
25933
25931
|
allowEmpty: true
|
|
25934
25932
|
};
|
|
25935
|
-
const styles$
|
|
25933
|
+
const styles$k = StyleSheet.create({
|
|
25936
25934
|
buttonStyle: {
|
|
25937
25935
|
backgroundColor: "white",
|
|
25938
25936
|
border: "1px solid #ccc",
|
|
@@ -26536,7 +26534,7 @@ var util = /*#__PURE__*/Object.freeze({
|
|
|
26536
26534
|
});
|
|
26537
26535
|
|
|
26538
26536
|
// @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
|
|
26539
|
-
const MovablePoint$
|
|
26537
|
+
const MovablePoint$3 = Graphie.MovablePoint;
|
|
26540
26538
|
// @ts-expect-error - TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
26541
26539
|
const MovableLine$2 = Graphie.MovableLine;
|
|
26542
26540
|
function isFlipped(newCoord, oldCoord, line) {
|
|
@@ -26618,7 +26616,7 @@ class FunctionGrapher extends React.Component {
|
|
|
26618
26616
|
}],
|
|
26619
26617
|
normalStyle: dashed,
|
|
26620
26618
|
highlightStyle: dashed
|
|
26621
|
-
}, _.map(asymptote, (coord, i) => /*#__PURE__*/React.createElement(MovablePoint$
|
|
26619
|
+
}, _.map(asymptote, (coord, i) => /*#__PURE__*/React.createElement(MovablePoint$3, {
|
|
26622
26620
|
key: `asymptoteCoord-${i}`,
|
|
26623
26621
|
coord: coord,
|
|
26624
26622
|
static: true,
|
|
@@ -26633,7 +26631,7 @@ class FunctionGrapher extends React.Component {
|
|
|
26633
26631
|
}
|
|
26634
26632
|
render() {
|
|
26635
26633
|
const pointForCoord = (coord, i) => {
|
|
26636
|
-
return /*#__PURE__*/React.createElement(MovablePoint$
|
|
26634
|
+
return /*#__PURE__*/React.createElement(MovablePoint$3, {
|
|
26637
26635
|
key: i,
|
|
26638
26636
|
coord: coord,
|
|
26639
26637
|
static: this.props.static,
|
|
@@ -27442,7 +27440,7 @@ const Label = Graphie.Label;
|
|
|
27442
27440
|
// @ts-expect-error - TS2339 - Property 'Line' does not exist on type 'typeof Graphie'.
|
|
27443
27441
|
const Line$2 = Graphie.Line;
|
|
27444
27442
|
// @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
|
|
27445
|
-
const MovablePoint$
|
|
27443
|
+
const MovablePoint$2 = Graphie.MovablePoint;
|
|
27446
27444
|
// @ts-expect-error - TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
27447
27445
|
const MovableLine$1 = Graphie.MovableLine;
|
|
27448
27446
|
// @ts-expect-error - TS2339 - Property 'Plot' does not exist on type 'typeof Graphie'.
|
|
@@ -27691,7 +27689,7 @@ class Interaction extends React.Component {
|
|
|
27691
27689
|
return [coordX, coordY];
|
|
27692
27690
|
}];
|
|
27693
27691
|
if (element.options.constraint === "snap") {
|
|
27694
|
-
constraints.push(MovablePoint$
|
|
27692
|
+
constraints.push(MovablePoint$2.constraints.snap(element.options.snap));
|
|
27695
27693
|
} else if (element.options.constraint === "x") {
|
|
27696
27694
|
constraints.push(coord => {
|
|
27697
27695
|
return [
|
|
@@ -27713,7 +27711,7 @@ class Interaction extends React.Component {
|
|
|
27713
27711
|
// TODO(eater): foo_[xyz] are hacky non-props to
|
|
27714
27712
|
// get the component to update when constraints
|
|
27715
27713
|
// change
|
|
27716
|
-
return /*#__PURE__*/React.createElement(MovablePoint$
|
|
27714
|
+
return /*#__PURE__*/React.createElement(MovablePoint$2, {
|
|
27717
27715
|
key: element.key,
|
|
27718
27716
|
coord: [
|
|
27719
27717
|
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
@@ -27748,7 +27746,7 @@ class Interaction extends React.Component {
|
|
|
27748
27746
|
return [coordX, coordY];
|
|
27749
27747
|
}];
|
|
27750
27748
|
if (element.options.constraint === "snap") {
|
|
27751
|
-
constraints.push(MovablePoint$
|
|
27749
|
+
constraints.push(MovablePoint$2.constraints.snap(element.options.snap));
|
|
27752
27750
|
} else if (element.options.constraint === "x") {
|
|
27753
27751
|
constraints.push(coord => {
|
|
27754
27752
|
return [
|
|
@@ -27789,14 +27787,14 @@ class Interaction extends React.Component {
|
|
|
27789
27787
|
foo_x: element.options.constraint,
|
|
27790
27788
|
foo_y: element.options.constraintFn,
|
|
27791
27789
|
foo_z: element.options.snap
|
|
27792
|
-
}, /*#__PURE__*/React.createElement(MovablePoint$
|
|
27790
|
+
}, /*#__PURE__*/React.createElement(MovablePoint$2, {
|
|
27793
27791
|
coord: start,
|
|
27794
27792
|
static: true,
|
|
27795
27793
|
normalStyle: {
|
|
27796
27794
|
stroke: "none",
|
|
27797
27795
|
fill: "none"
|
|
27798
27796
|
}
|
|
27799
|
-
}), /*#__PURE__*/React.createElement(MovablePoint$
|
|
27797
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$2, {
|
|
27800
27798
|
coord: end,
|
|
27801
27799
|
static: true,
|
|
27802
27800
|
normalStyle: {
|
|
@@ -28353,7 +28351,7 @@ const defaultGraphConfig = {
|
|
|
28353
28351
|
width: 0,
|
|
28354
28352
|
height: 0,
|
|
28355
28353
|
labels: [],
|
|
28356
|
-
|
|
28354
|
+
disableKeyboardInteraction: false
|
|
28357
28355
|
};
|
|
28358
28356
|
const GraphConfigContext = /*#__PURE__*/createContext(defaultGraphConfig);
|
|
28359
28357
|
function useGraphConfig() {
|
|
@@ -28490,6 +28488,28 @@ const segmentsIntersect = ([[a, b], [c, d]], [[p, q], [r, s]]) => {
|
|
|
28490
28488
|
}
|
|
28491
28489
|
};
|
|
28492
28490
|
|
|
28491
|
+
// Finds the unique intersection point between two rays. Returns undefined if
|
|
28492
|
+
// there is not exactly one intersection point. The first point in each of the
|
|
28493
|
+
// given ray "segments" should be the initial point of the ray. The second point
|
|
28494
|
+
// can be any arbitrary point on the ray different from the initial point.
|
|
28495
|
+
function findIntersectionOfRays([[a, b], [c, d]], [[p, q], [r, s]]) {
|
|
28496
|
+
// See https://stackoverflow.com/a/24392281/7347484 for an explanation of
|
|
28497
|
+
// the determinant and lambda values.
|
|
28498
|
+
const determinant = (c - a) * (s - q) - (r - p) * (d - b);
|
|
28499
|
+
if (determinant === 0) {
|
|
28500
|
+
return undefined;
|
|
28501
|
+
} else {
|
|
28502
|
+
const lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / determinant;
|
|
28503
|
+
const gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / determinant;
|
|
28504
|
+
if (lambda <= 0 || gamma >= 1) {
|
|
28505
|
+
return undefined;
|
|
28506
|
+
}
|
|
28507
|
+
const initialPoint = [a, b];
|
|
28508
|
+
const direction = vec.sub([c, d], initialPoint);
|
|
28509
|
+
return vec.add(initialPoint, vec.scale(direction, lambda));
|
|
28510
|
+
}
|
|
28511
|
+
}
|
|
28512
|
+
|
|
28493
28513
|
// This file contains helper functions for working with angles.
|
|
28494
28514
|
|
|
28495
28515
|
function convertDegreesToRadians(degrees) {
|
|
@@ -28501,6 +28521,8 @@ function convertDegreesToRadians(degrees) {
|
|
|
28501
28521
|
function calculateAngleInDegrees([x, y]) {
|
|
28502
28522
|
return Math.atan2(y, x) * 180 / Math.PI;
|
|
28503
28523
|
}
|
|
28524
|
+
|
|
28525
|
+
// Converts polar coordinates to cartesian. The th(eta) parameter is in degrees.
|
|
28504
28526
|
function polar(r, th) {
|
|
28505
28527
|
if (typeof r === "number") {
|
|
28506
28528
|
r = [r, r];
|
|
@@ -29106,7 +29128,7 @@ const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
|
29106
29128
|
width: "24",
|
|
29107
29129
|
height: "24",
|
|
29108
29130
|
viewBox: "0 0 24 24",
|
|
29109
|
-
className: css(styles$
|
|
29131
|
+
className: css(styles$j.icon)
|
|
29110
29132
|
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
29111
29133
|
id: "a",
|
|
29112
29134
|
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 +29159,7 @@ const HiddenIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
|
29137
29159
|
width: "24",
|
|
29138
29160
|
height: "24",
|
|
29139
29161
|
viewBox: "0 0 24 24",
|
|
29140
|
-
className: css(styles$
|
|
29162
|
+
className: css(styles$j.icon)
|
|
29141
29163
|
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
29142
29164
|
id: "a",
|
|
29143
29165
|
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 +29193,20 @@ const HUD = ({
|
|
|
29171
29193
|
let state;
|
|
29172
29194
|
let icon;
|
|
29173
29195
|
if (enabled) {
|
|
29174
|
-
state = styles$
|
|
29196
|
+
state = styles$j.enabled;
|
|
29175
29197
|
icon = /*#__PURE__*/React.createElement(VisibleIcon, null);
|
|
29176
29198
|
} else {
|
|
29177
|
-
state = styles$
|
|
29199
|
+
state = styles$j.disabled;
|
|
29178
29200
|
icon = /*#__PURE__*/React.createElement(HiddenIcon, null);
|
|
29179
29201
|
}
|
|
29180
29202
|
return /*#__PURE__*/React.createElement("button", {
|
|
29181
|
-
className: css(styles$
|
|
29203
|
+
className: css(styles$j.hud, _fixedPosition && styles$j.hudFixedPosition, state),
|
|
29182
29204
|
onClick: e => {
|
|
29183
29205
|
onClick();
|
|
29184
29206
|
}
|
|
29185
29207
|
}, icon, message);
|
|
29186
29208
|
};
|
|
29187
|
-
const styles$
|
|
29209
|
+
const styles$j = StyleSheet.create({
|
|
29188
29210
|
hud: {
|
|
29189
29211
|
boxSizing: "border-box",
|
|
29190
29212
|
height: 36,
|
|
@@ -29234,19 +29256,19 @@ const styles$k = StyleSheet.create({
|
|
|
29234
29256
|
}
|
|
29235
29257
|
});
|
|
29236
29258
|
|
|
29237
|
-
const
|
|
29259
|
+
const InfoTipBase = props => {
|
|
29238
29260
|
return /*#__PURE__*/React.createElement(Tooltip$1, {
|
|
29239
29261
|
content: /*#__PURE__*/React.createElement(Body, {
|
|
29240
|
-
style: styles$
|
|
29262
|
+
style: styles$i.body
|
|
29241
29263
|
}, props.children),
|
|
29242
29264
|
placement: "right"
|
|
29243
29265
|
}, /*#__PURE__*/React.createElement(PhosphorIcon, {
|
|
29244
29266
|
size: "small",
|
|
29245
29267
|
icon: questionIcon,
|
|
29246
|
-
style: styles$
|
|
29268
|
+
style: styles$i.spacingLeft
|
|
29247
29269
|
}));
|
|
29248
29270
|
};
|
|
29249
|
-
const styles$
|
|
29271
|
+
const styles$i = StyleSheet.create({
|
|
29250
29272
|
spacingLeft: {
|
|
29251
29273
|
marginInlineStart: spacing.xxxSmall_4
|
|
29252
29274
|
},
|
|
@@ -29278,7 +29300,7 @@ class InfoTip extends React.Component {
|
|
|
29278
29300
|
|
|
29279
29301
|
render() {
|
|
29280
29302
|
if (this.state.didMount) {
|
|
29281
|
-
return /*#__PURE__*/React.createElement(
|
|
29303
|
+
return /*#__PURE__*/React.createElement(InfoTipBase, this.props);
|
|
29282
29304
|
}
|
|
29283
29305
|
return /*#__PURE__*/React.createElement("div", null);
|
|
29284
29306
|
}
|
|
@@ -29325,7 +29347,7 @@ class MultiButtonGroup extends React.Component {
|
|
|
29325
29347
|
id: "" + i,
|
|
29326
29348
|
key: "" + i,
|
|
29327
29349
|
ref: "button" + i,
|
|
29328
|
-
className: css(styles$
|
|
29350
|
+
className: css(styles$h.buttonStyle, selected && styles$h.selectedStyle),
|
|
29329
29351
|
onClick: () => this.toggleSelect(button.value)
|
|
29330
29352
|
}, button.content || "" + button.value);
|
|
29331
29353
|
});
|
|
@@ -29341,7 +29363,7 @@ MultiButtonGroup.defaultProps = {
|
|
|
29341
29363
|
values: [],
|
|
29342
29364
|
allowEmpty: true
|
|
29343
29365
|
};
|
|
29344
|
-
const styles$
|
|
29366
|
+
const styles$h = StyleSheet.create({
|
|
29345
29367
|
buttonStyle: {
|
|
29346
29368
|
backgroundColor: "white",
|
|
29347
29369
|
border: "1px solid #ccc",
|
|
@@ -29566,62 +29588,6 @@ NumberInput.defaultProps = {
|
|
|
29566
29588
|
useArrowKeys: false
|
|
29567
29589
|
};
|
|
29568
29590
|
|
|
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
29591
|
const truth = () => true;
|
|
29626
29592
|
|
|
29627
29593
|
/* A minor abstraction on top of NumberInput for ranges
|
|
@@ -29683,7 +29649,6 @@ var components = /*#__PURE__*/Object.freeze({
|
|
|
29683
29649
|
MathInput: MathInput,
|
|
29684
29650
|
MultiButtonGroup: MultiButtonGroup,
|
|
29685
29651
|
NumberInput: NumberInput,
|
|
29686
|
-
PropCheckBox: PropCheckBox,
|
|
29687
29652
|
RangeInput: RangeInput,
|
|
29688
29653
|
SvgImage: SvgImage,
|
|
29689
29654
|
TextInput: TextInput,
|
|
@@ -29837,8 +29802,9 @@ const lockedFigureColors = {
|
|
|
29837
29802
|
};
|
|
29838
29803
|
const lockedFigureFillStyles = {
|
|
29839
29804
|
none: 0,
|
|
29840
|
-
|
|
29841
|
-
translucent: 0.4
|
|
29805
|
+
white: 1,
|
|
29806
|
+
translucent: 0.4,
|
|
29807
|
+
solid: 1
|
|
29842
29808
|
};
|
|
29843
29809
|
const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
|
|
29844
29810
|
|
|
@@ -29847,7 +29813,7 @@ const LockedEllipse = props => {
|
|
|
29847
29813
|
center,
|
|
29848
29814
|
radius,
|
|
29849
29815
|
angle,
|
|
29850
|
-
color,
|
|
29816
|
+
color: color$1,
|
|
29851
29817
|
fillStyle,
|
|
29852
29818
|
strokeStyle
|
|
29853
29819
|
} = props;
|
|
@@ -29857,11 +29823,21 @@ const LockedEllipse = props => {
|
|
|
29857
29823
|
angle: angle,
|
|
29858
29824
|
fillOpacity: lockedFigureFillStyles[fillStyle],
|
|
29859
29825
|
strokeStyle: strokeStyle,
|
|
29860
|
-
color: lockedFigureColors[color]
|
|
29826
|
+
color: lockedFigureColors[color$1]
|
|
29827
|
+
// We need to override the svg props if we want to have a
|
|
29828
|
+
// different fill color than the stroke color (specifically,
|
|
29829
|
+
// in the case where the fillStyle is "white").
|
|
29830
|
+
,
|
|
29831
|
+
svgEllipseProps: {
|
|
29832
|
+
style: {
|
|
29833
|
+
fill: fillStyle === "white" ? color.white : lockedFigureColors[color$1]
|
|
29834
|
+
}
|
|
29835
|
+
}
|
|
29861
29836
|
});
|
|
29862
29837
|
};
|
|
29863
29838
|
|
|
29864
29839
|
const LockedFunction = props => {
|
|
29840
|
+
const [equation, setEquation] = useState();
|
|
29865
29841
|
const {
|
|
29866
29842
|
color,
|
|
29867
29843
|
strokeStyle,
|
|
@@ -29873,7 +29849,14 @@ const LockedFunction = props => {
|
|
|
29873
29849
|
style: strokeStyle,
|
|
29874
29850
|
domain
|
|
29875
29851
|
};
|
|
29876
|
-
|
|
29852
|
+
useEffect(() => {
|
|
29853
|
+
// Parsing the equation in a "useEffect" hook saves about 2ms each frame
|
|
29854
|
+
// when the learner is interacting with the graph (i.e. moving points).
|
|
29855
|
+
setEquation(KAS.parse(props.equation).expr);
|
|
29856
|
+
}, [props.equation]);
|
|
29857
|
+
if (typeof equation === "undefined") {
|
|
29858
|
+
return null;
|
|
29859
|
+
}
|
|
29877
29860
|
return /*#__PURE__*/React.createElement("g", {
|
|
29878
29861
|
className: "locked-function"
|
|
29879
29862
|
}, directionalAxis === "x" && /*#__PURE__*/React.createElement(Plot$3.OfX, _extends({
|
|
@@ -30064,7 +30047,7 @@ const LockedPoint = props => {
|
|
|
30064
30047
|
const LockedPolygon = props => {
|
|
30065
30048
|
const {
|
|
30066
30049
|
points,
|
|
30067
|
-
color,
|
|
30050
|
+
color: color$1,
|
|
30068
30051
|
showVertices,
|
|
30069
30052
|
fillStyle,
|
|
30070
30053
|
strokeStyle
|
|
@@ -30075,12 +30058,21 @@ const LockedPolygon = props => {
|
|
|
30075
30058
|
points: [...points],
|
|
30076
30059
|
fillOpacity: lockedFigureFillStyles[fillStyle],
|
|
30077
30060
|
strokeStyle: strokeStyle,
|
|
30078
|
-
color: lockedFigureColors[color]
|
|
30061
|
+
color: lockedFigureColors[color$1]
|
|
30062
|
+
// We need to override the svg props if we want to have a
|
|
30063
|
+
// different fill color than the stroke color (specifically,
|
|
30064
|
+
// in the case where the fillStyle is "white").
|
|
30065
|
+
,
|
|
30066
|
+
svgPolygonProps: {
|
|
30067
|
+
style: {
|
|
30068
|
+
fill: fillStyle === "white" ? color.white : lockedFigureColors[color$1]
|
|
30069
|
+
}
|
|
30070
|
+
}
|
|
30079
30071
|
}), showVertices && points.map((point, index) => /*#__PURE__*/React.createElement(Point$2, {
|
|
30080
30072
|
key: `locked-polygon-point-${index}`,
|
|
30081
30073
|
x: point[X],
|
|
30082
30074
|
y: point[Y],
|
|
30083
|
-
color: lockedFigureColors[color]
|
|
30075
|
+
color: lockedFigureColors[color$1]
|
|
30084
30076
|
})));
|
|
30085
30077
|
};
|
|
30086
30078
|
|
|
@@ -30321,7 +30313,7 @@ function useDraggable(args) {
|
|
|
30321
30313
|
gestureTarget: target,
|
|
30322
30314
|
onMove,
|
|
30323
30315
|
point,
|
|
30324
|
-
|
|
30316
|
+
constrainKeyboardMovement
|
|
30325
30317
|
} = args;
|
|
30326
30318
|
const [dragging, setDragging] = React.useState(false);
|
|
30327
30319
|
const {
|
|
@@ -30344,6 +30336,7 @@ function useDraggable(args) {
|
|
|
30344
30336
|
event == null || event.stopPropagation();
|
|
30345
30337
|
const isKeyboard = type.includes("key");
|
|
30346
30338
|
if (isKeyboard) {
|
|
30339
|
+
invariant(event instanceof KeyboardEvent);
|
|
30347
30340
|
event == null || event.preventDefault();
|
|
30348
30341
|
|
|
30349
30342
|
// When a key is held down, we see multiple "keydown" events,
|
|
@@ -30355,6 +30348,11 @@ function useDraggable(args) {
|
|
|
30355
30348
|
if (type === "keyup") {
|
|
30356
30349
|
return;
|
|
30357
30350
|
}
|
|
30351
|
+
if (typeof constrainKeyboardMovement === "object") {
|
|
30352
|
+
const destination = constrainKeyboardMovement[directionForKey[event.key]];
|
|
30353
|
+
onMove(destination != null ? destination : point);
|
|
30354
|
+
return;
|
|
30355
|
+
}
|
|
30358
30356
|
const {
|
|
30359
30357
|
direction: yDownDirection,
|
|
30360
30358
|
altKey,
|
|
@@ -30375,7 +30373,7 @@ function useDraggable(args) {
|
|
|
30375
30373
|
for (const dx of tests) {
|
|
30376
30374
|
// Transform the test back into the point's coordinate system
|
|
30377
30375
|
const testMovement = vec.scale(direction, dx);
|
|
30378
|
-
const testPoint =
|
|
30376
|
+
const testPoint = constrainKeyboardMovement(vec.transform(vec.add(vec.transform(point, userTransform), testMovement), inverseTransform));
|
|
30379
30377
|
if (vec.dist(testPoint, point) > min) {
|
|
30380
30378
|
onMove(testPoint);
|
|
30381
30379
|
break;
|
|
@@ -30395,7 +30393,7 @@ function useDraggable(args) {
|
|
|
30395
30393
|
return;
|
|
30396
30394
|
}
|
|
30397
30395
|
const movement = vec.transform(pixelMovement, inverseViewTransform);
|
|
30398
|
-
onMove(
|
|
30396
|
+
onMove(vec.transform(vec.add(pickup.current, movement), inverseTransform));
|
|
30399
30397
|
}
|
|
30400
30398
|
}, {
|
|
30401
30399
|
target,
|
|
@@ -30407,6 +30405,12 @@ function useDraggable(args) {
|
|
|
30407
30405
|
dragging
|
|
30408
30406
|
};
|
|
30409
30407
|
}
|
|
30408
|
+
const directionForKey = {
|
|
30409
|
+
ArrowLeft: "left",
|
|
30410
|
+
ArrowRight: "right",
|
|
30411
|
+
ArrowUp: "up",
|
|
30412
|
+
ArrowDown: "down"
|
|
30413
|
+
};
|
|
30410
30414
|
function getInverseTransform(transform) {
|
|
30411
30415
|
const invert = vec.matrixInvert(transform);
|
|
30412
30416
|
invariant(invert !== null, "Could not invert transform matrix. A parent transformation matrix might be degenerative (mapping 2D space to a line).");
|
|
@@ -30456,7 +30460,7 @@ const MovablePointView = /*#__PURE__*/forwardRef((props, hitboxRef) => {
|
|
|
30456
30460
|
range,
|
|
30457
30461
|
markings,
|
|
30458
30462
|
showTooltips,
|
|
30459
|
-
|
|
30463
|
+
disableKeyboardInteraction
|
|
30460
30464
|
} = useGraphConfig();
|
|
30461
30465
|
const {
|
|
30462
30466
|
point,
|
|
@@ -30498,7 +30502,7 @@ const MovablePointView = /*#__PURE__*/forwardRef((props, hitboxRef) => {
|
|
|
30498
30502
|
cursor
|
|
30499
30503
|
},
|
|
30500
30504
|
"data-testid": "movable-point",
|
|
30501
|
-
tabIndex:
|
|
30505
|
+
tabIndex: disableKeyboardInteraction ? -1 : tabIndex(focusBehavior)
|
|
30502
30506
|
}, /*#__PURE__*/React.createElement("circle", {
|
|
30503
30507
|
className: "movable-point-hitbox",
|
|
30504
30508
|
r: hitboxSizePx / 2,
|
|
@@ -30587,7 +30591,7 @@ const MovableLine = props => {
|
|
|
30587
30591
|
function useControlPoint(point, color, onMovePoint) {
|
|
30588
30592
|
const {
|
|
30589
30593
|
snapStep,
|
|
30590
|
-
|
|
30594
|
+
disableKeyboardInteraction
|
|
30591
30595
|
} = useGraphConfig();
|
|
30592
30596
|
const [focused, setFocused] = useState(false);
|
|
30593
30597
|
const keyboardHandleRef = useRef(null);
|
|
@@ -30595,7 +30599,7 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
30595
30599
|
gestureTarget: keyboardHandleRef,
|
|
30596
30600
|
point,
|
|
30597
30601
|
onMove: onMovePoint,
|
|
30598
|
-
|
|
30602
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30599
30603
|
});
|
|
30600
30604
|
const visiblePointRef = useRef(null);
|
|
30601
30605
|
const {
|
|
@@ -30604,12 +30608,12 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
30604
30608
|
gestureTarget: visiblePointRef,
|
|
30605
30609
|
point,
|
|
30606
30610
|
onMove: onMovePoint,
|
|
30607
|
-
|
|
30611
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30608
30612
|
});
|
|
30609
30613
|
const focusableHandle = /*#__PURE__*/React.createElement("g", {
|
|
30610
30614
|
"data-testid": "movable-point__focusable-handle",
|
|
30611
30615
|
className: "movable-point__focusable-handle",
|
|
30612
|
-
tabIndex:
|
|
30616
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
30613
30617
|
ref: keyboardHandleRef,
|
|
30614
30618
|
onFocus: () => setFocused(true),
|
|
30615
30619
|
onBlur: () => setFocused(false)
|
|
@@ -30643,7 +30647,7 @@ const Line$1 = props => {
|
|
|
30643
30647
|
range,
|
|
30644
30648
|
graphDimensionsInPixels,
|
|
30645
30649
|
snapStep,
|
|
30646
|
-
|
|
30650
|
+
disableKeyboardInteraction
|
|
30647
30651
|
} = useGraphConfig();
|
|
30648
30652
|
let startExtend = undefined;
|
|
30649
30653
|
let endExtend = undefined;
|
|
@@ -30661,11 +30665,11 @@ const Line$1 = props => {
|
|
|
30661
30665
|
onMove: newPoint => {
|
|
30662
30666
|
onMove(vec.sub(newPoint, start));
|
|
30663
30667
|
},
|
|
30664
|
-
|
|
30668
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30665
30669
|
});
|
|
30666
30670
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("g", {
|
|
30667
30671
|
ref: line,
|
|
30668
|
-
tabIndex:
|
|
30672
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
30669
30673
|
className: "movable-line",
|
|
30670
30674
|
"data-testid": "movable-line",
|
|
30671
30675
|
style: {
|
|
@@ -31128,7 +31132,7 @@ function calculateBisectorPoint(point1, point2, vertex, isReflex, allowReflex, a
|
|
|
31128
31132
|
return scaledBisector;
|
|
31129
31133
|
}
|
|
31130
31134
|
|
|
31131
|
-
const
|
|
31135
|
+
const MovablePoint$1 = props => {
|
|
31132
31136
|
const {
|
|
31133
31137
|
snapStep
|
|
31134
31138
|
} = useGraphConfig();
|
|
@@ -31138,16 +31142,15 @@ const StyledMovablePoint = props => {
|
|
|
31138
31142
|
onMove,
|
|
31139
31143
|
cursor,
|
|
31140
31144
|
color: color$1 = color.blue,
|
|
31141
|
-
|
|
31145
|
+
constrain = p => snap(snapStep, p)
|
|
31142
31146
|
} = props;
|
|
31143
|
-
const snapToValue = snapTo != null ? snapTo : "grid";
|
|
31144
31147
|
const {
|
|
31145
31148
|
dragging
|
|
31146
31149
|
} = useDraggable({
|
|
31147
31150
|
gestureTarget: elementRef,
|
|
31148
31151
|
point,
|
|
31149
31152
|
onMove,
|
|
31150
|
-
|
|
31153
|
+
constrainKeyboardMovement: constrain
|
|
31151
31154
|
});
|
|
31152
31155
|
return /*#__PURE__*/React.createElement(MovablePointView, {
|
|
31153
31156
|
ref: elementRef,
|
|
@@ -31163,8 +31166,10 @@ const StyledMovablePoint = props => {
|
|
|
31163
31166
|
};
|
|
31164
31167
|
|
|
31165
31168
|
const PolygonGraph = props => {
|
|
31166
|
-
const [focused, setFocused] = React.useState(false);
|
|
31167
31169
|
const [hovered, setHovered] = React.useState(false);
|
|
31170
|
+
// This is more so required for the re-rendering that occurs when state
|
|
31171
|
+
// updates; specifically with regard to line weighting and polygon focus.
|
|
31172
|
+
const [focusVisible, setFocusVisible] = React.useState(false);
|
|
31168
31173
|
const {
|
|
31169
31174
|
dispatch
|
|
31170
31175
|
} = props;
|
|
@@ -31174,10 +31179,10 @@ const PolygonGraph = props => {
|
|
|
31174
31179
|
showSides,
|
|
31175
31180
|
range,
|
|
31176
31181
|
snapStep,
|
|
31177
|
-
snapTo
|
|
31182
|
+
snapTo = "grid"
|
|
31178
31183
|
} = props.graphState;
|
|
31179
31184
|
const {
|
|
31180
|
-
|
|
31185
|
+
disableKeyboardInteraction
|
|
31181
31186
|
} = useGraphConfig();
|
|
31182
31187
|
|
|
31183
31188
|
// TODO(benchristel): can the default set of points be removed here? I don't
|
|
@@ -31185,7 +31190,7 @@ const PolygonGraph = props => {
|
|
|
31185
31190
|
const points = coords != null ? coords : [[0, 0]];
|
|
31186
31191
|
const ref = React.useRef(null);
|
|
31187
31192
|
const dragReferencePoint = points[0];
|
|
31188
|
-
const
|
|
31193
|
+
const constrain = ["angles", "sides"].includes(snapTo) ? p => p : p => snap(snapStep, p);
|
|
31189
31194
|
const {
|
|
31190
31195
|
dragging
|
|
31191
31196
|
} = useDraggable({
|
|
@@ -31195,16 +31200,15 @@ const PolygonGraph = props => {
|
|
|
31195
31200
|
const delta = vec.sub(newPoint, dragReferencePoint);
|
|
31196
31201
|
dispatch(actions.polygon.moveAll(delta));
|
|
31197
31202
|
},
|
|
31198
|
-
|
|
31203
|
+
constrainKeyboardMovement: constrain
|
|
31199
31204
|
});
|
|
31200
|
-
const active = hovered || focused || dragging;
|
|
31201
31205
|
const lastMoveTime = React.useRef(0);
|
|
31202
31206
|
const lines = getLines(points);
|
|
31203
31207
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Polygon, {
|
|
31204
31208
|
points: [...points],
|
|
31205
31209
|
color: "var(--movable-line-stroke-color)",
|
|
31206
31210
|
svgPolygonProps: {
|
|
31207
|
-
strokeWidth:
|
|
31211
|
+
strokeWidth: focusVisible ? "var(--movable-line-stroke-weight-active)" : "var(--movable-line-stroke-weight)",
|
|
31208
31212
|
style: {
|
|
31209
31213
|
fill: "transparent"
|
|
31210
31214
|
}
|
|
@@ -31219,11 +31223,10 @@ const PolygonGraph = props => {
|
|
|
31219
31223
|
key: "angle-" + i,
|
|
31220
31224
|
centerPoint: point,
|
|
31221
31225
|
endPoints: [pt1, pt2],
|
|
31222
|
-
active: active,
|
|
31223
31226
|
range: range,
|
|
31224
31227
|
polygonLines: lines,
|
|
31225
31228
|
showAngles: !!showAngles,
|
|
31226
|
-
snapTo:
|
|
31229
|
+
snapTo: snapTo
|
|
31227
31230
|
});
|
|
31228
31231
|
}), showSides && lines.map(([start, end], i) => {
|
|
31229
31232
|
const [x, y] = vec.midpoint(start, end);
|
|
@@ -31238,21 +31241,29 @@ const PolygonGraph = props => {
|
|
|
31238
31241
|
color: "transparent",
|
|
31239
31242
|
svgPolygonProps: {
|
|
31240
31243
|
ref,
|
|
31241
|
-
tabIndex:
|
|
31244
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
31242
31245
|
strokeWidth: TARGET_SIZE,
|
|
31243
31246
|
style: {
|
|
31244
31247
|
cursor: dragging ? "grabbing" : "grab",
|
|
31245
31248
|
fill: hovered ? "var(--mafs-blue)" : "transparent"
|
|
31246
31249
|
},
|
|
31247
|
-
onFocus: () => setFocused(true),
|
|
31248
|
-
onBlur: () => setFocused(false),
|
|
31249
31250
|
onMouseEnter: () => setHovered(true),
|
|
31250
31251
|
onMouseLeave: () => setHovered(false),
|
|
31252
|
+
// Required to remove line weighting when user clicks away
|
|
31253
|
+
// from the focused polygon
|
|
31254
|
+
onKeyDownCapture: () => {
|
|
31255
|
+
setFocusVisible(hasFocusVisible(ref.current));
|
|
31256
|
+
},
|
|
31257
|
+
// Required for lines to darken on focus
|
|
31258
|
+
onFocus: () => setFocusVisible(hasFocusVisible(ref.current)),
|
|
31259
|
+
// Required for line weighting to update on blur. Without this,
|
|
31260
|
+
// the user has to hover over the shape for it to update
|
|
31261
|
+
onBlur: () => setFocusVisible(hasFocusVisible(ref.current)),
|
|
31251
31262
|
className: "movable-polygon"
|
|
31252
31263
|
}
|
|
31253
|
-
}), points.map((point, i) => /*#__PURE__*/React.createElement(
|
|
31264
|
+
}), points.map((point, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31254
31265
|
key: "point-" + i,
|
|
31255
|
-
|
|
31266
|
+
constrain: constrain,
|
|
31256
31267
|
point: point,
|
|
31257
31268
|
onMove: destination => {
|
|
31258
31269
|
const now = Date.now();
|
|
@@ -31271,6 +31282,20 @@ function getLines(points) {
|
|
|
31271
31282
|
return [point, next];
|
|
31272
31283
|
});
|
|
31273
31284
|
}
|
|
31285
|
+
const hasFocusVisible = element => {
|
|
31286
|
+
const matches = selector => {
|
|
31287
|
+
var _element$matches;
|
|
31288
|
+
return (_element$matches = element == null ? void 0 : element.matches(selector)) != null ? _element$matches : false;
|
|
31289
|
+
};
|
|
31290
|
+
try {
|
|
31291
|
+
return matches(":focus-visible");
|
|
31292
|
+
} catch (e) {
|
|
31293
|
+
// jsdom doesn't support :focus-visible
|
|
31294
|
+
// (see https://github.com/jsdom/jsdom/issues/3426),
|
|
31295
|
+
// so the call to matches(":focus-visible") will fail in tests.
|
|
31296
|
+
return matches(":focus");
|
|
31297
|
+
}
|
|
31298
|
+
};
|
|
31274
31299
|
|
|
31275
31300
|
function getGradableGraph(state, initialGraph) {
|
|
31276
31301
|
if (!state.hasBeenInteractedWith) {
|
|
@@ -31364,7 +31389,7 @@ function CircleGraph(props) {
|
|
|
31364
31389
|
center: center,
|
|
31365
31390
|
radius: getRadius(graphState),
|
|
31366
31391
|
onMove: c => dispatch(actions.circle.moveCenter(c))
|
|
31367
|
-
}), /*#__PURE__*/React.createElement(
|
|
31392
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31368
31393
|
point: radiusPoint,
|
|
31369
31394
|
cursor: "ew-resize",
|
|
31370
31395
|
onMove: newRadiusPoint => {
|
|
@@ -31380,7 +31405,7 @@ function MovableCircle(props) {
|
|
|
31380
31405
|
} = props;
|
|
31381
31406
|
const {
|
|
31382
31407
|
snapStep,
|
|
31383
|
-
|
|
31408
|
+
disableKeyboardInteraction
|
|
31384
31409
|
} = useGraphConfig();
|
|
31385
31410
|
const draggableRef = useRef(null);
|
|
31386
31411
|
const {
|
|
@@ -31389,13 +31414,13 @@ function MovableCircle(props) {
|
|
|
31389
31414
|
gestureTarget: draggableRef,
|
|
31390
31415
|
point: center,
|
|
31391
31416
|
onMove,
|
|
31392
|
-
|
|
31417
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
31393
31418
|
});
|
|
31394
31419
|
const [centerPx] = useTransformVectorsToPixels(center);
|
|
31395
31420
|
const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
|
|
31396
31421
|
return /*#__PURE__*/React.createElement("g", {
|
|
31397
31422
|
ref: draggableRef,
|
|
31398
|
-
tabIndex:
|
|
31423
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
31399
31424
|
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
|
|
31400
31425
|
}, /*#__PURE__*/React.createElement("ellipse", {
|
|
31401
31426
|
className: "focus-ring",
|
|
@@ -31476,7 +31501,7 @@ function QuadraticGraph(props) {
|
|
|
31476
31501
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Plot$3.OfX, {
|
|
31477
31502
|
y: y,
|
|
31478
31503
|
color: color.blue
|
|
31479
|
-
}), coords.map((coord, i) => /*#__PURE__*/React.createElement(
|
|
31504
|
+
}), coords.map((coord, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31480
31505
|
key: "point-" + i,
|
|
31481
31506
|
point: coord,
|
|
31482
31507
|
onMove: destination => dispatch(actions.quadratic.movePoint(i, destination))
|
|
@@ -31536,7 +31561,7 @@ function SinusoidGraph(props) {
|
|
|
31536
31561
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Plot$3.OfX, {
|
|
31537
31562
|
y: x => computeSine(x, coeffRef.current),
|
|
31538
31563
|
color: color.blue
|
|
31539
|
-
}), coords.map((coord, i) => /*#__PURE__*/React.createElement(
|
|
31564
|
+
}), coords.map((coord, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31540
31565
|
key: "point-" + i,
|
|
31541
31566
|
point: coord,
|
|
31542
31567
|
onMove: destination => dispatch(actions.sinusoid.movePoint(i, destination))
|
|
@@ -31592,7 +31617,6 @@ function AngleGraph(props) {
|
|
|
31592
31617
|
showAngles,
|
|
31593
31618
|
range,
|
|
31594
31619
|
allowReflexAngles,
|
|
31595
|
-
angleOffsetDeg,
|
|
31596
31620
|
snapDegrees
|
|
31597
31621
|
} = graphState;
|
|
31598
31622
|
|
|
@@ -31630,8 +31654,6 @@ function AngleGraph(props) {
|
|
|
31630
31654
|
coords: endPoints,
|
|
31631
31655
|
allowReflexAngles: allowReflexAngles || false,
|
|
31632
31656
|
// Whether to allow reflex angles or not
|
|
31633
|
-
angleOffsetDeg: angleOffsetDeg || 0,
|
|
31634
|
-
// The angle offset from the x-axis
|
|
31635
31657
|
snapDegrees: snapDegrees || 1,
|
|
31636
31658
|
// The multiple of degrees to snap to
|
|
31637
31659
|
range: range,
|
|
@@ -31639,19 +31661,66 @@ function AngleGraph(props) {
|
|
|
31639
31661
|
};
|
|
31640
31662
|
|
|
31641
31663
|
// 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
|
-
|
|
31664
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, svgLines, /*#__PURE__*/React.createElement(Angle, angleParams), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31665
|
+
point: coords[1],
|
|
31666
|
+
constrain: p => p,
|
|
31667
|
+
onMove: destination => dispatch(actions.angle.movePoint(1, destination))
|
|
31668
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31669
|
+
point: coords[0],
|
|
31670
|
+
constrain: getAngleSideConstraint(coords[0], coords[1], snapDegrees || 1),
|
|
31671
|
+
onMove: destination => dispatch(actions.angle.movePoint(0, destination))
|
|
31672
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31673
|
+
point: coords[2],
|
|
31674
|
+
constrain: getAngleSideConstraint(coords[2], coords[1], snapDegrees || 1),
|
|
31675
|
+
onMove: destination => dispatch(actions.angle.movePoint(2, destination))
|
|
31676
|
+
}));
|
|
31677
|
+
}
|
|
31678
|
+
const positiveX = [1, 0];
|
|
31679
|
+
const negativeX = [-1, 0];
|
|
31680
|
+
const positiveY = [0, 1];
|
|
31681
|
+
const negativeY = [0, -1];
|
|
31682
|
+
function getAngleSideConstraint(sidePoint, vertex, snapDegrees) {
|
|
31683
|
+
var _findIntersectionOfRa, _findIntersectionOfRa2, _findIntersectionOfRa3, _findIntersectionOfRa4;
|
|
31684
|
+
const currentAngle = calculateAngleInDegrees(vec.sub(sidePoint, vertex));
|
|
31685
|
+
|
|
31686
|
+
// Find the rays that start at the current point and point up, down, left
|
|
31687
|
+
// and right.
|
|
31688
|
+
const leftRay = [sidePoint, vec.add(sidePoint, negativeX)];
|
|
31689
|
+
const rightRay = [sidePoint, vec.add(sidePoint, positiveX)];
|
|
31690
|
+
const upRay = [sidePoint, vec.add(sidePoint, positiveY)];
|
|
31691
|
+
const downRay = [sidePoint, vec.add(sidePoint, negativeY)];
|
|
31692
|
+
|
|
31693
|
+
// find the angles that lie one snap step clockwise and counter-clockwise
|
|
31694
|
+
// from the current angle. These are the angles to which the side can be
|
|
31695
|
+
// moved.
|
|
31696
|
+
const oneStepCounterClockwise = currentAngle + snapDegrees;
|
|
31697
|
+
const oneStepClockwise = currentAngle - snapDegrees;
|
|
31698
|
+
|
|
31699
|
+
// find the rays that start from the vertex and point in the direction of
|
|
31700
|
+
// the angles we just computed.
|
|
31701
|
+
const counterClockwiseRay = [vertex, vec.add(vertex, polar(1, oneStepCounterClockwise))];
|
|
31702
|
+
const clockwiseRay = [vertex, vec.add(vertex, polar(1, oneStepClockwise))];
|
|
31703
|
+
|
|
31704
|
+
// find the intersections of those rays with the horizontal and vertical
|
|
31705
|
+
// rays extending from the sidePoint. These intersections are the points to
|
|
31706
|
+
// which sidePoint can move that will result in a rotation of `snapDegrees`.
|
|
31707
|
+
const left = (_findIntersectionOfRa = findIntersectionOfRays(leftRay, counterClockwiseRay)) != null ? _findIntersectionOfRa : findIntersectionOfRays(leftRay, clockwiseRay);
|
|
31708
|
+
const right = (_findIntersectionOfRa2 = findIntersectionOfRays(rightRay, counterClockwiseRay)) != null ? _findIntersectionOfRa2 : findIntersectionOfRays(rightRay, clockwiseRay);
|
|
31709
|
+
const up = (_findIntersectionOfRa3 = findIntersectionOfRays(upRay, counterClockwiseRay)) != null ? _findIntersectionOfRa3 : findIntersectionOfRays(upRay, clockwiseRay);
|
|
31710
|
+
const down = (_findIntersectionOfRa4 = findIntersectionOfRays(downRay, counterClockwiseRay)) != null ? _findIntersectionOfRa4 : findIntersectionOfRays(downRay, clockwiseRay);
|
|
31711
|
+
return {
|
|
31712
|
+
up: up != null ? up : sidePoint,
|
|
31713
|
+
down: down != null ? down : sidePoint,
|
|
31714
|
+
left: left != null ? left : sidePoint,
|
|
31715
|
+
right: right != null ? right : sidePoint
|
|
31716
|
+
};
|
|
31648
31717
|
}
|
|
31649
31718
|
|
|
31650
31719
|
function PointGraph(props) {
|
|
31651
31720
|
const {
|
|
31652
31721
|
dispatch
|
|
31653
31722
|
} = props;
|
|
31654
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, props.graphState.coords.map((point, i) => /*#__PURE__*/React.createElement(
|
|
31723
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, props.graphState.coords.map((point, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
31655
31724
|
key: i,
|
|
31656
31725
|
point: point,
|
|
31657
31726
|
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination))
|
|
@@ -31683,7 +31752,7 @@ function Protractor() {
|
|
|
31683
31752
|
gestureTarget: draggableRef,
|
|
31684
31753
|
onMove: setCenter,
|
|
31685
31754
|
point: center,
|
|
31686
|
-
|
|
31755
|
+
constrainKeyboardMovement: point => bound$1({
|
|
31687
31756
|
snapStep,
|
|
31688
31757
|
range,
|
|
31689
31758
|
point
|
|
@@ -31799,7 +31868,8 @@ const MafsGraph = props => {
|
|
|
31799
31868
|
state,
|
|
31800
31869
|
dispatch,
|
|
31801
31870
|
labels,
|
|
31802
|
-
hintMode
|
|
31871
|
+
hintMode,
|
|
31872
|
+
readOnly
|
|
31803
31873
|
} = props;
|
|
31804
31874
|
const [width, height] = props.box;
|
|
31805
31875
|
const tickStep = props.step;
|
|
@@ -31815,7 +31885,7 @@ const MafsGraph = props => {
|
|
|
31815
31885
|
width,
|
|
31816
31886
|
height,
|
|
31817
31887
|
labels,
|
|
31818
|
-
hintMode
|
|
31888
|
+
disableKeyboardInteraction: hintMode || readOnly
|
|
31819
31889
|
}
|
|
31820
31890
|
}, /*#__PURE__*/React.createElement(View, {
|
|
31821
31891
|
className: "mafs-graph",
|
|
@@ -32173,6 +32243,9 @@ const getAngleCoords = params => {
|
|
|
32173
32243
|
if (graph.coords) {
|
|
32174
32244
|
return graph.coords;
|
|
32175
32245
|
}
|
|
32246
|
+
if (graph.startCoords) {
|
|
32247
|
+
return graph.startCoords;
|
|
32248
|
+
}
|
|
32176
32249
|
const {
|
|
32177
32250
|
snapDegrees,
|
|
32178
32251
|
angleOffsetDeg
|
|
@@ -32202,6 +32275,7 @@ const getAngleCoords = params => {
|
|
|
32202
32275
|
return coords;
|
|
32203
32276
|
};
|
|
32204
32277
|
|
|
32278
|
+
const minDistanceBetweenAngleVertexAndSidePoint = 2;
|
|
32205
32279
|
function interactiveGraphReducer(state, action) {
|
|
32206
32280
|
switch (action.type) {
|
|
32207
32281
|
case REINITIALIZE:
|
|
@@ -32367,21 +32441,28 @@ function doMovePoint(state, action) {
|
|
|
32367
32441
|
case "angle":
|
|
32368
32442
|
// If the index is 1, we are moving the vertex of the angle,
|
|
32369
32443
|
// which will move the other two points as well
|
|
32370
|
-
|
|
32371
|
-
|
|
32444
|
+
const newState = (() => {
|
|
32445
|
+
if (action.index === 1) {
|
|
32446
|
+
const updatedCoords = boundAndSnapAngleVertex(state, action);
|
|
32447
|
+
return _extends({}, state, {
|
|
32448
|
+
hasBeenInteractedWith: true,
|
|
32449
|
+
coords: updatedCoords
|
|
32450
|
+
});
|
|
32451
|
+
}
|
|
32372
32452
|
return _extends({}, state, {
|
|
32373
32453
|
hasBeenInteractedWith: true,
|
|
32374
|
-
coords:
|
|
32454
|
+
coords: setAtIndex({
|
|
32455
|
+
array: state.coords,
|
|
32456
|
+
index: action.index,
|
|
32457
|
+
newValue: boundAndSnapAngleEndPoints(action.destination, state, action.index)
|
|
32458
|
+
})
|
|
32375
32459
|
});
|
|
32460
|
+
})();
|
|
32461
|
+
if (angleSidePointsTooCloseToVertex(newState)) {
|
|
32462
|
+
// cancel the move
|
|
32463
|
+
return state;
|
|
32376
32464
|
}
|
|
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
|
-
});
|
|
32465
|
+
return newState;
|
|
32385
32466
|
case "polygon":
|
|
32386
32467
|
let newValue;
|
|
32387
32468
|
if (state.snapTo === "sides") {
|
|
@@ -32470,11 +32551,7 @@ function doMoveCenter(state, action) {
|
|
|
32470
32551
|
case "circle":
|
|
32471
32552
|
{
|
|
32472
32553
|
// 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
|
-
});
|
|
32554
|
+
const constrainedCenter = boundAndSnapToGrid(action.destination, state);
|
|
32478
32555
|
|
|
32479
32556
|
// Reposition the radius point based on the new center
|
|
32480
32557
|
// (spread to make sure we're not going to mutate anything)
|
|
@@ -32508,10 +32585,10 @@ function doMoveRadiusPoint(state, action) {
|
|
|
32508
32585
|
case "circle":
|
|
32509
32586
|
{
|
|
32510
32587
|
const [xMin, xMax] = state.range[X];
|
|
32511
|
-
const nextRadiusPoint = [
|
|
32588
|
+
const nextRadiusPoint = snap(state.snapStep, [
|
|
32512
32589
|
// Constrain to graph range
|
|
32513
32590
|
// The +0 is to convert -0 to +0
|
|
32514
|
-
clamp(action.destination[X] + 0, xMin, xMax), state.center[1]];
|
|
32591
|
+
clamp(action.destination[X] + 0, xMin, xMax), state.center[1]]);
|
|
32515
32592
|
if (_.isEqual(nextRadiusPoint, state.center)) {
|
|
32516
32593
|
return state;
|
|
32517
32594
|
}
|
|
@@ -32593,17 +32670,16 @@ function boundAndSnapAngleVertex({
|
|
|
32593
32670
|
|
|
32594
32671
|
// Get the current and upcoming positions of the vertex
|
|
32595
32672
|
const startingVertex = coordsCopy[1];
|
|
32596
|
-
|
|
32597
|
-
|
|
32598
|
-
|
|
32599
|
-
|
|
32600
|
-
|
|
32673
|
+
|
|
32674
|
+
// Prevent the vertex from getting too close to the edge, so that all
|
|
32675
|
+
// points of the angle can fit within the graph bounds.
|
|
32676
|
+
const insetAmount = vec.add(snapStep, [minDistanceBetweenAngleVertexAndSidePoint, minDistanceBetweenAngleVertexAndSidePoint]);
|
|
32677
|
+
const newVertex = clampToBox(inset(insetAmount, range), snap(snapStep, destination));
|
|
32601
32678
|
|
|
32602
32679
|
// Get the vector from the starting vertex to the new vertex
|
|
32603
32680
|
const delta = vec.add(newVertex, reverseVector(startingVertex));
|
|
32604
32681
|
|
|
32605
32682
|
// Apply the delta to each of the other two points so that the angle is maintained
|
|
32606
|
-
let valid = true;
|
|
32607
32683
|
const newPoints = {};
|
|
32608
32684
|
for (const i of [0, 2]) {
|
|
32609
32685
|
const oldPoint = coordsCopy[i];
|
|
@@ -32612,21 +32688,13 @@ function boundAndSnapAngleVertex({
|
|
|
32612
32688
|
angle *= Math.PI / 180;
|
|
32613
32689
|
newPoint = constrainToBoundsOnAngle(newPoint, angle, range, snapStep);
|
|
32614
32690
|
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
32691
|
}
|
|
32621
32692
|
|
|
32622
32693
|
// Update the vertex after snapping to the snapStep
|
|
32623
32694
|
newPoints[1] = newVertex;
|
|
32624
|
-
|
|
32625
|
-
|
|
32626
|
-
|
|
32627
|
-
coordsCopy[i] = newPoint;
|
|
32628
|
-
});
|
|
32629
|
-
}
|
|
32695
|
+
Object.entries(newPoints).forEach(([i, newPoint]) => {
|
|
32696
|
+
coordsCopy[i] = newPoint;
|
|
32697
|
+
});
|
|
32630
32698
|
return coordsCopy;
|
|
32631
32699
|
}
|
|
32632
32700
|
|
|
@@ -32691,10 +32759,17 @@ function boundAndSnapAngleEndPoints(destinationPoint, {
|
|
|
32691
32759
|
|
|
32692
32760
|
// Snap the angle to the nearest multiple of snapDegrees (if provided)
|
|
32693
32761
|
angle = Math.round((angle - offsetDegrees) / snap) * snap + offsetDegrees;
|
|
32694
|
-
|
|
32762
|
+
|
|
32763
|
+
// add 0.01 to prevent rounding errors from causing the point to snap to
|
|
32764
|
+
// a location that is too close to the vertex.
|
|
32765
|
+
const minDistance = minDistanceBetweenAngleVertexAndSidePoint + 0.01;
|
|
32766
|
+
const distance = Math.max(vec.dist(coordsCopy[index], vertex), minDistance);
|
|
32695
32767
|
const snappedValue = vec.add(vertex, polar(distance, angle));
|
|
32696
32768
|
return snappedValue;
|
|
32697
32769
|
}
|
|
32770
|
+
function angleSidePointsTooCloseToVertex(state) {
|
|
32771
|
+
return tooClose(state.coords[0], state.coords[1], state.range) || tooClose(state.coords[2], state.coords[1], state.range);
|
|
32772
|
+
}
|
|
32698
32773
|
function boundAndSnapToPolygonAngle(destinationPoint, {
|
|
32699
32774
|
range,
|
|
32700
32775
|
coords
|
|
@@ -32917,7 +32992,12 @@ const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
32917
32992
|
useEffect(() => {
|
|
32918
32993
|
dispatch(changeRange([[xMinRange, xMaxRange], [yMinRange, yMaxRange]]));
|
|
32919
32994
|
}, [dispatch, xMinRange, xMaxRange, yMinRange, yMaxRange]);
|
|
32995
|
+
|
|
32996
|
+
// Update the graph whenever any of the following values changes.
|
|
32997
|
+
// This is necessary to keep the graph previews in sync with the updated
|
|
32998
|
+
// graph settings within the interative graph editor.
|
|
32920
32999
|
const numSegments = graph.type === "segment" ? graph.numSegments : null;
|
|
33000
|
+
const numPoints = graph.type === "point" ? graph.numPoints : null;
|
|
32921
33001
|
const numSides = graph.type === "polygon" ? graph.numSides : null;
|
|
32922
33002
|
const snapTo = graph.type === "polygon" ? graph.snapTo : null;
|
|
32923
33003
|
const showAngles = graph.type === "polygon" ? graph.showAngles : null;
|
|
@@ -32932,7 +33012,7 @@ const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
32932
33012
|
if (latestPropsRef.current !== originalPropsRef.current) {
|
|
32933
33013
|
dispatch(reinitialize(latestPropsRef.current));
|
|
32934
33014
|
}
|
|
32935
|
-
}, [graph.type, numSegments, numSides, snapTo, showAngles, showSides, latestPropsRef, graph.startCoords]);
|
|
33015
|
+
}, [graph.type, numPoints, numSegments, numSides, snapTo, showAngles, showSides, latestPropsRef, graph.startCoords]);
|
|
32936
33016
|
return /*#__PURE__*/React.createElement(MafsGraph, _extends({}, props, {
|
|
32937
33017
|
state: state,
|
|
32938
33018
|
dispatch: dispatch
|
|
@@ -34242,6 +34322,7 @@ class InteractiveGraph extends React.Component {
|
|
|
34242
34322
|
// Mafs shim
|
|
34243
34323
|
const mafsFlags = (_this$props$apiOption = this.props.apiOptions) == null || (_this$props$apiOption = _this$props$apiOption.flags) == null ? void 0 : _this$props$apiOption["mafs"];
|
|
34244
34324
|
if (shouldUseMafs(mafsFlags, this.props.graph)) {
|
|
34325
|
+
var _this$props$apiOption2;
|
|
34245
34326
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
34246
34327
|
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
34247
34328
|
const snapStep = this.props.snapStep || Util.snapStepFromGridStep(gridStep);
|
|
@@ -34251,7 +34332,8 @@ class InteractiveGraph extends React.Component {
|
|
|
34251
34332
|
snapStep: snapStep,
|
|
34252
34333
|
box: box,
|
|
34253
34334
|
showTooltips: !!this.props.showTooltips,
|
|
34254
|
-
hintMode: this.props.hintMode
|
|
34335
|
+
hintMode: this.props.hintMode,
|
|
34336
|
+
readOnly: (_this$props$apiOption2 = this.props.apiOptions) == null ? void 0 : _this$props$apiOption2.readOnly
|
|
34255
34337
|
}));
|
|
34256
34338
|
}
|
|
34257
34339
|
return /*#__PURE__*/React.createElement(LegacyInteractiveGraph, _extends({
|
|
@@ -44170,7 +44252,7 @@ const init = function init(options) {
|
|
|
44170
44252
|
|
|
44171
44253
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44172
44254
|
const libName = "@khanacademy/perseus";
|
|
44173
|
-
const libVersion = "
|
|
44255
|
+
const libVersion = "28.1.0";
|
|
44174
44256
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44175
44257
|
|
|
44176
44258
|
const apiVersion = {
|
|
@@ -44725,7 +44807,6 @@ const context = /*#__PURE__*/React.createContext(defaultContext);
|
|
|
44725
44807
|
const {
|
|
44726
44808
|
mapObject
|
|
44727
44809
|
} = objective_;
|
|
44728
|
-
/* eslint-disable-next-line react/no-unsafe */
|
|
44729
44810
|
class ServerItemRenderer extends React.Component {
|
|
44730
44811
|
constructor(props) {
|
|
44731
44812
|
super(props);
|
|
@@ -46091,7 +46172,16 @@ class MultiRenderer extends React.Component {
|
|
|
46091
46172
|
// _annotateRendererArray() needs this
|
|
46092
46173
|
ref: null,
|
|
46093
46174
|
makeRenderer: () => /*#__PURE__*/React.createElement(HintsRenderer, _extends({}, this._getRendererProps(), {
|
|
46094
|
-
findExternalWidgets: findExternalWidgets
|
|
46175
|
+
findExternalWidgets: findExternalWidgets
|
|
46176
|
+
// Note(Jeremy): The MultiRenderer codebase types are
|
|
46177
|
+
// slightly different from the rest of the codebase.
|
|
46178
|
+
// Ideally `HintNode` would spread the `Hint` type into it,
|
|
46179
|
+
// but there is a difference in optionality of `widgets`
|
|
46180
|
+
// and `images` and that causes a huge cascade of type
|
|
46181
|
+
// errors (they are truly optional, but most of our code
|
|
46182
|
+
// assumes they're provided/set). Ignoring this for now.
|
|
46183
|
+
// @ts-expect-error - TS2769 - Type 'HintNode' is not assignable to type 'Hint'.
|
|
46184
|
+
,
|
|
46095
46185
|
hints: [hint]
|
|
46096
46186
|
}))
|
|
46097
46187
|
};
|
|
@@ -47750,5 +47840,5 @@ const EditorJsonify = {
|
|
|
47750
47840
|
}
|
|
47751
47841
|
};
|
|
47752
47842
|
|
|
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 };
|
|
47843
|
+
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
47844
|
//# sourceMappingURL=index.js.map
|