@khanacademy/perseus 27.1.0 → 28.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/image-loader.d.ts +2 -2
- package/dist/components/{info-tip.d.ts → info-tip/index.d.ts} +2 -2
- package/dist/components/info-tip/info-tip-base.d.ts +6 -0
- package/dist/components.d.ts +0 -1
- package/dist/es/index.js +445 -341
- 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 +433 -327
- package/dist/index.js.map +1 -1
- package/dist/interactive2/movable-point.d.ts +3 -3
- package/dist/perseus-api.d.ts +5 -2
- package/dist/perseus-types.d.ts +10 -6
- package/dist/renderer.d.ts +2 -1
- package/dist/server-item-renderer.d.ts +5 -2
- 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 +8 -8
- package/dist/util/{katex-preprocess.d.ts → tex-preprocess.d.ts} +1 -1
- package/dist/widgets/expression.d.ts +32 -14
- 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 +10 -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 +10 -4
- package/package.json +6 -6
- package/dist/components/info-tip/info-tip.d.ts +0 -6
- package/dist/components/prop-check-box.d.ts +0 -4
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ var Clickable = require('@khanacademy/wonder-blocks-clickable');
|
|
|
18
18
|
var wonderBlocksPopover = require('@khanacademy/wonder-blocks-popover');
|
|
19
19
|
var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
|
|
20
20
|
var $ = require('jquery');
|
|
21
|
+
var uuid = require('uuid');
|
|
21
22
|
var PropTypes = require('prop-types');
|
|
22
23
|
var kmath = require('@khanacademy/kmath');
|
|
23
24
|
var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
|
|
@@ -35,11 +36,11 @@ var debounce$1 = require('lodash.debounce');
|
|
|
35
36
|
var mafs = require('mafs');
|
|
36
37
|
var wonderBlocksIcon = require('@khanacademy/wonder-blocks-icon');
|
|
37
38
|
var questionIcon = require('@phosphor-icons/core/regular/question.svg');
|
|
38
|
-
var createReactClass = require('create-react-class');
|
|
39
39
|
var react = require('@use-gesture/react');
|
|
40
40
|
var Switch = require('@khanacademy/wonder-blocks-switch');
|
|
41
41
|
var Pill = require('@khanacademy/wonder-blocks-pill');
|
|
42
42
|
var reactPopper = require('react-popper');
|
|
43
|
+
var createReactClass = require('create-react-class');
|
|
43
44
|
var Link = require('@khanacademy/wonder-blocks-link');
|
|
44
45
|
|
|
45
46
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -81,9 +82,9 @@ var caretDown__default = /*#__PURE__*/_interopDefaultLegacy(caretDown);
|
|
|
81
82
|
var caretUp__default = /*#__PURE__*/_interopDefaultLegacy(caretUp);
|
|
82
83
|
var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce$1);
|
|
83
84
|
var questionIcon__default = /*#__PURE__*/_interopDefaultLegacy(questionIcon);
|
|
84
|
-
var createReactClass__default = /*#__PURE__*/_interopDefaultLegacy(createReactClass);
|
|
85
85
|
var Switch__default = /*#__PURE__*/_interopDefaultLegacy(Switch);
|
|
86
86
|
var Pill__default = /*#__PURE__*/_interopDefaultLegacy(Pill);
|
|
87
|
+
var createReactClass__default = /*#__PURE__*/_interopDefaultLegacy(createReactClass);
|
|
87
88
|
var Link__default = /*#__PURE__*/_interopDefaultLegacy(Link);
|
|
88
89
|
|
|
89
90
|
function _extends() {
|
|
@@ -354,7 +355,9 @@ const mockStrings = {
|
|
|
354
355
|
loading: "Loading...",
|
|
355
356
|
videoTranscript: "See video transcript",
|
|
356
357
|
somethingWrong: "Something went wrong.",
|
|
357
|
-
videoWrapper: "Khan Academy video wrapper"
|
|
358
|
+
videoWrapper: "Khan Academy video wrapper",
|
|
359
|
+
mathInputTitle: "mathematics keyboard",
|
|
360
|
+
mathInputDescription: "Use keyboard/mouse to interact with math-based input fields"
|
|
358
361
|
};
|
|
359
362
|
|
|
360
363
|
/**
|
|
@@ -386,6 +389,26 @@ function PerseusI18nContextProvider(_ref) {
|
|
|
386
389
|
}
|
|
387
390
|
const usePerseusI18n = () => React.useContext(PerseusI18nContext);
|
|
388
391
|
|
|
392
|
+
/*
|
|
393
|
+
* A11y (Accessibility) style rules
|
|
394
|
+
* These are used to mark up areas on the site that should only be readable
|
|
395
|
+
* when using a screen reader.
|
|
396
|
+
*/
|
|
397
|
+
var a11y = aphrodite.StyleSheet.create({
|
|
398
|
+
// Make content only visible to screen readers.
|
|
399
|
+
// Both collegeboard.org and Bootstrap 3 use this exact implementation.
|
|
400
|
+
srOnly: {
|
|
401
|
+
border: 0,
|
|
402
|
+
clip: "rect(0,0,0,0)",
|
|
403
|
+
height: 1,
|
|
404
|
+
margin: -1,
|
|
405
|
+
overflow: "hidden",
|
|
406
|
+
padding: 0,
|
|
407
|
+
position: "absolute",
|
|
408
|
+
width: 1
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
|
|
389
412
|
const debounce = (func, delay) => {
|
|
390
413
|
let timer = null;
|
|
391
414
|
return function () {
|
|
@@ -588,11 +611,12 @@ class InnerMathInput extends React__namespace.Component {
|
|
|
588
611
|
"mq-editable-field": true,
|
|
589
612
|
"mq-math-mode": true
|
|
590
613
|
});
|
|
614
|
+
const popoverContentUniqueId = uuid.v4().slice(0, 8);
|
|
591
615
|
if (this.props.className) {
|
|
592
616
|
className = className + " " + this.props.className;
|
|
593
617
|
}
|
|
594
618
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
595
|
-
style: [styles$
|
|
619
|
+
style: [styles$D.outerWrapper, this.state.focused && styles$D.wrapperFocused, this.props.hasError && styles$D.wrapperError]
|
|
596
620
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
597
621
|
style: {
|
|
598
622
|
display: "flex",
|
|
@@ -620,16 +644,21 @@ class InnerMathInput extends React__namespace.Component {
|
|
|
620
644
|
opened: this.state.keypadOpen,
|
|
621
645
|
onClose: () => this.closeKeypad(),
|
|
622
646
|
dismissEnabled: true,
|
|
623
|
-
|
|
647
|
+
"aria-label": this.context.strings.mathInputTitle,
|
|
648
|
+
"aria-describedby": `popover-content-${popoverContentUniqueId}`,
|
|
649
|
+
content: () => /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.HeadingMedium, {
|
|
650
|
+
id: `popover-content-${popoverContentUniqueId}`,
|
|
651
|
+
style: a11y.srOnly
|
|
652
|
+
}, this.context.strings.mathInputDescription), /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
|
|
624
653
|
closeButtonVisible: true,
|
|
625
|
-
style: styles$
|
|
654
|
+
style: styles$D.popoverContent
|
|
626
655
|
}, /*#__PURE__*/React__namespace.createElement(mathInput.DesktopKeypad, _extends({
|
|
627
656
|
onAnalyticsEvent: this.props.analytics.onAnalyticsEvent,
|
|
628
657
|
extraKeys: this.props.extraKeys,
|
|
629
658
|
onClickKey: this.handleKeypadPress,
|
|
630
659
|
cursorContext: this.state.cursorContext,
|
|
631
660
|
convertDotToTimes: this.props.convertDotToTimes
|
|
632
|
-
}, this.props.keypadButtonSets ?? mapButtonSets(this.props?.buttonSets))))
|
|
661
|
+
}, this.props.keypadButtonSets ?? mapButtonSets(this.props?.buttonSets)))))
|
|
633
662
|
}, this.props.buttonsVisible === "never" ? /*#__PURE__*/React__namespace.createElement(MathInputIcon, {
|
|
634
663
|
hovered: false,
|
|
635
664
|
focused: false,
|
|
@@ -687,9 +716,9 @@ const MathInputIcon = _ref => {
|
|
|
687
716
|
fillColor = wonderBlocksTokens.color.offBlack;
|
|
688
717
|
break;
|
|
689
718
|
}
|
|
690
|
-
const dynamicClass = active || focused ? styles$
|
|
719
|
+
const dynamicClass = active || focused ? styles$D.iconActive : styles$D.iconInactive;
|
|
691
720
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
692
|
-
style: [styles$
|
|
721
|
+
style: [styles$D.iconContainer, dynamicClass]
|
|
693
722
|
}, /*#__PURE__*/React__namespace.createElement("svg", {
|
|
694
723
|
xmlns: "http://www.w3.org/2000/svg",
|
|
695
724
|
width: "16",
|
|
@@ -734,7 +763,7 @@ const inputFocused = {
|
|
|
734
763
|
borderColor: wonderBlocksTokens.color.blue,
|
|
735
764
|
margin: -1
|
|
736
765
|
};
|
|
737
|
-
const styles$
|
|
766
|
+
const styles$D = aphrodite.StyleSheet.create({
|
|
738
767
|
iconContainer: {
|
|
739
768
|
display: "flex",
|
|
740
769
|
justifyContent: "center",
|
|
@@ -1263,26 +1292,6 @@ const ClassNames = {
|
|
|
1263
1292
|
MOBILE: "perseus-mobile"
|
|
1264
1293
|
};
|
|
1265
1294
|
|
|
1266
|
-
/*
|
|
1267
|
-
* A11y (Accessibility) style rules
|
|
1268
|
-
* These are used to mark up areas on the site that should only be readable
|
|
1269
|
-
* when using a screen reader.
|
|
1270
|
-
*/
|
|
1271
|
-
var a11y = aphrodite.StyleSheet.create({
|
|
1272
|
-
// Make content only visible to screen readers.
|
|
1273
|
-
// Both collegeboard.org and Bootstrap 3 use this exact implementation.
|
|
1274
|
-
srOnly: {
|
|
1275
|
-
border: 0,
|
|
1276
|
-
clip: "rect(0,0,0,0)",
|
|
1277
|
-
height: 1,
|
|
1278
|
-
margin: -1,
|
|
1279
|
-
overflow: "hidden",
|
|
1280
|
-
padding: 0,
|
|
1281
|
-
position: "absolute",
|
|
1282
|
-
width: 1
|
|
1283
|
-
}
|
|
1284
|
-
});
|
|
1285
|
-
|
|
1286
1295
|
const KhanMath = {
|
|
1287
1296
|
// Simplify formulas before display
|
|
1288
1297
|
cleanMath: function (expr) {
|
|
@@ -2587,7 +2596,7 @@ class Expression extends React__namespace.Component {
|
|
|
2587
2596
|
render() {
|
|
2588
2597
|
if (this.props.apiOptions.customKeypad) {
|
|
2589
2598
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
2590
|
-
className: aphrodite.css(styles$
|
|
2599
|
+
className: aphrodite.css(styles$C.mobileLabelInputWrapper)
|
|
2591
2600
|
}, !!this.props.visibleLabel && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
|
|
2592
2601
|
htmlFor: this._textareaId,
|
|
2593
2602
|
tag: "label"
|
|
@@ -2621,7 +2630,7 @@ class Expression extends React__namespace.Component {
|
|
|
2621
2630
|
ERROR_TITLE
|
|
2622
2631
|
} = this.context.strings;
|
|
2623
2632
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
2624
|
-
className: aphrodite.css(styles$
|
|
2633
|
+
className: aphrodite.css(styles$C.desktopLabelInputWrapper)
|
|
2625
2634
|
}, !!this.props.visibleLabel && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
|
|
2626
2635
|
htmlFor: this._textareaId,
|
|
2627
2636
|
tag: "label"
|
|
@@ -2662,7 +2671,7 @@ class Expression extends React__namespace.Component {
|
|
|
2662
2671
|
}))));
|
|
2663
2672
|
}
|
|
2664
2673
|
}
|
|
2665
|
-
const styles$
|
|
2674
|
+
const styles$C = aphrodite.StyleSheet.create({
|
|
2666
2675
|
mobileLabelInputWrapper: {
|
|
2667
2676
|
padding: "15px 4px 0"
|
|
2668
2677
|
},
|
|
@@ -9039,8 +9048,8 @@ function findChildOrAdd(elem, className) {
|
|
|
9039
9048
|
return $child;
|
|
9040
9049
|
}
|
|
9041
9050
|
var Tex$1 = {
|
|
9042
|
-
// Process a node and add math inside of it. This
|
|
9043
|
-
// format the math
|
|
9051
|
+
// Process a node and add math inside of it. This uses MathJax to
|
|
9052
|
+
// format the math.
|
|
9044
9053
|
//
|
|
9045
9054
|
// elem: The element which the math should be added to.
|
|
9046
9055
|
//
|
|
@@ -15435,7 +15444,7 @@ const DEFAULT_STATE$1 = {
|
|
|
15435
15444
|
// TODO(benchristel): this is a memory leak. We add items to
|
|
15436
15445
|
// tooltipResetFunctions, but never remove them.
|
|
15437
15446
|
const tooltipResetFunctions = [];
|
|
15438
|
-
class MovablePoint$
|
|
15447
|
+
class MovablePoint$5 {
|
|
15439
15448
|
graphie;
|
|
15440
15449
|
movable;
|
|
15441
15450
|
state;
|
|
@@ -15743,9 +15752,9 @@ class MovablePoint$4 {
|
|
|
15743
15752
|
* Displays a tooltip above the point, replacing any previous contents. If
|
|
15744
15753
|
* there is no tooltip initialized, adds the tooltip.
|
|
15745
15754
|
*
|
|
15746
|
-
* If the type of contents is string, the contents will be rendered
|
|
15747
|
-
*
|
|
15748
|
-
*
|
|
15755
|
+
* If the type of contents is string, the contents will be rendered as TeX
|
|
15756
|
+
* Otherwise, the content will be assumed to be a DOM node and will be
|
|
15757
|
+
* appended inside the tooltip.
|
|
15749
15758
|
*/
|
|
15750
15759
|
_showTooltip(contents) {
|
|
15751
15760
|
if (!this._tooltip) {
|
|
@@ -16568,10 +16577,10 @@ ___default["default"].extend(MovablePolygon.prototype, {
|
|
|
16568
16577
|
});
|
|
16569
16578
|
|
|
16570
16579
|
const Interactive2 = {
|
|
16571
|
-
MovablePoint: MovablePoint$
|
|
16580
|
+
MovablePoint: MovablePoint$5,
|
|
16572
16581
|
addMovablePoint: function (graphie, options) {
|
|
16573
16582
|
const movable = new Movable(graphie, {});
|
|
16574
|
-
return new MovablePoint$
|
|
16583
|
+
return new MovablePoint$5(graphie, movable, options);
|
|
16575
16584
|
},
|
|
16576
16585
|
MovableLine: MovableLine$4,
|
|
16577
16586
|
addMovableLine: function (graphie, options) {
|
|
@@ -16613,7 +16622,7 @@ const Interactive2 = {
|
|
|
16613
16622
|
}
|
|
16614
16623
|
};
|
|
16615
16624
|
|
|
16616
|
-
const MovablePoint$
|
|
16625
|
+
const MovablePoint$4 = GraphieClasses.createClass({
|
|
16617
16626
|
displayName: "MovablePoint",
|
|
16618
16627
|
movableProps: ["children"],
|
|
16619
16628
|
_getProps: function () {
|
|
@@ -16671,7 +16680,7 @@ const MovablePoint$3 = GraphieClasses.createClass({
|
|
|
16671
16680
|
});
|
|
16672
16681
|
|
|
16673
16682
|
// Include helper methods, such as MovablePoint.constrain.snap()
|
|
16674
|
-
___default["default"].extend(MovablePoint$
|
|
16683
|
+
___default["default"].extend(MovablePoint$4, Interactive2.MovablePoint);
|
|
16675
16684
|
const MovableLine$3 = GraphieClasses.createClass({
|
|
16676
16685
|
displayName: "MovableLine",
|
|
16677
16686
|
movableProps: ["children"],
|
|
@@ -16841,7 +16850,7 @@ var Movables = {
|
|
|
16841
16850
|
Label: Label$1,
|
|
16842
16851
|
Line: Line$3,
|
|
16843
16852
|
MovableLine: MovableLine$3,
|
|
16844
|
-
MovablePoint: MovablePoint$
|
|
16853
|
+
MovablePoint: MovablePoint$4,
|
|
16845
16854
|
Parabola: Parabola,
|
|
16846
16855
|
Path: Path,
|
|
16847
16856
|
Plot: Plot$2,
|
|
@@ -17199,17 +17208,15 @@ class ImageLoader extends React__namespace.Component {
|
|
|
17199
17208
|
src,
|
|
17200
17209
|
imgProps
|
|
17201
17210
|
} = this.props;
|
|
17202
|
-
let onKeyUp
|
|
17203
|
-
let onKeyDown
|
|
17211
|
+
let onKeyUp;
|
|
17212
|
+
let onKeyDown;
|
|
17204
17213
|
if (imgProps.onClick != null) {
|
|
17205
|
-
// @ts-expect-error - TS2322 - Type '(e: React.KeyboardEvent) => void' is not assignable to type 'null'.
|
|
17206
17214
|
onKeyUp = e => {
|
|
17207
17215
|
// 13 is enter key, 32 is space key
|
|
17208
17216
|
if (e.keyCode === 13 || e.keyCode === 32) {
|
|
17209
17217
|
imgProps.onClick && imgProps.onClick(e);
|
|
17210
17218
|
}
|
|
17211
17219
|
};
|
|
17212
|
-
// @ts-expect-error - TS2322 - Type '(e: React.KeyboardEvent) => void' is not assignable to type 'null'.
|
|
17213
17220
|
onKeyDown = e => {
|
|
17214
17221
|
// 32 is space key
|
|
17215
17222
|
if (e.keyCode === 32) {
|
|
@@ -17220,12 +17227,8 @@ class ImageLoader extends React__namespace.Component {
|
|
|
17220
17227
|
}
|
|
17221
17228
|
const staticUrl = getDependencies().staticUrl;
|
|
17222
17229
|
return /*#__PURE__*/React__namespace.createElement("img", _extends({
|
|
17223
|
-
src: staticUrl(src)
|
|
17224
|
-
|
|
17225
|
-
,
|
|
17226
|
-
onKeyUp: onKeyUp
|
|
17227
|
-
// @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'KeyboardEventHandler<HTMLImageElement> | undefined'.
|
|
17228
|
-
,
|
|
17230
|
+
src: staticUrl(src),
|
|
17231
|
+
onKeyUp: onKeyUp,
|
|
17229
17232
|
onKeyDown: onKeyDown
|
|
17230
17233
|
}, imgProps));
|
|
17231
17234
|
};
|
|
@@ -17716,18 +17719,14 @@ class SvgImage extends React__namespace.Component {
|
|
|
17716
17719
|
allowFullBleed: this.props.allowFullBleed && isImageProbablyPhotograph(imageSrc)
|
|
17717
17720
|
}, /*#__PURE__*/React__namespace.createElement(ImageLoader, {
|
|
17718
17721
|
src: imageSrc,
|
|
17719
|
-
imgProps: imageProps
|
|
17720
|
-
// @ts-expect-error - TS2322 - Type '(() => Element) | null' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>> | null | undefined'.
|
|
17721
|
-
,
|
|
17722
|
+
imgProps: imageProps,
|
|
17722
17723
|
preloader: preloader,
|
|
17723
17724
|
onUpdate: this.handleUpdate
|
|
17724
17725
|
}), extraGraphie);
|
|
17725
17726
|
}
|
|
17726
17727
|
imageProps.style = dimensions;
|
|
17727
17728
|
return /*#__PURE__*/React__namespace.createElement(ImageLoader, {
|
|
17728
|
-
src: imageSrc
|
|
17729
|
-
// @ts-expect-error - TS2322 - Type '(() => Element) | null' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>> | null | undefined'.
|
|
17730
|
-
,
|
|
17729
|
+
src: imageSrc,
|
|
17731
17730
|
preloader: preloader,
|
|
17732
17731
|
imgProps: imageProps,
|
|
17733
17732
|
onUpdate: this.handleUpdate
|
|
@@ -17777,9 +17776,7 @@ class SvgImage extends React__namespace.Component {
|
|
|
17777
17776
|
}, /*#__PURE__*/React__namespace.createElement(ImageLoader, {
|
|
17778
17777
|
src: imageUrl,
|
|
17779
17778
|
onLoad: this.onImageLoad,
|
|
17780
|
-
onUpdate: this.handleUpdate
|
|
17781
|
-
// @ts-expect-error - TS2322 - Type '(() => Element) | null' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>> | null | undefined'.
|
|
17782
|
-
,
|
|
17779
|
+
onUpdate: this.handleUpdate,
|
|
17783
17780
|
preloader: preloader,
|
|
17784
17781
|
imgProps: imageProps
|
|
17785
17782
|
}), graphie, extraGraphie);
|
|
@@ -17791,9 +17788,7 @@ class SvgImage extends React__namespace.Component {
|
|
|
17791
17788
|
}, /*#__PURE__*/React__namespace.createElement(ImageLoader, {
|
|
17792
17789
|
src: imageUrl,
|
|
17793
17790
|
onLoad: this.onImageLoad,
|
|
17794
|
-
onUpdate: this.handleUpdate
|
|
17795
|
-
// @ts-expect-error - TS2322 - Type '(() => Element) | null' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>> | null | undefined'.
|
|
17796
|
-
,
|
|
17791
|
+
onUpdate: this.handleUpdate,
|
|
17797
17792
|
preloader: preloader,
|
|
17798
17793
|
imgProps: imageProps
|
|
17799
17794
|
}), graphie);
|
|
@@ -18371,33 +18366,33 @@ class Lint extends React__namespace.Component {
|
|
|
18371
18366
|
let warningText;
|
|
18372
18367
|
let warningTextStyle;
|
|
18373
18368
|
if (this.props.severity === Severity.Error) {
|
|
18374
|
-
severityStyle = styles$
|
|
18369
|
+
severityStyle = styles$B.indicatorError;
|
|
18375
18370
|
warningText = "Error";
|
|
18376
|
-
warningTextStyle = styles$
|
|
18371
|
+
warningTextStyle = styles$B.publishBlockingError;
|
|
18377
18372
|
} else if (this.props.severity === Severity.Warning) {
|
|
18378
|
-
severityStyle = styles$
|
|
18373
|
+
severityStyle = styles$B.indicatorWarning;
|
|
18379
18374
|
warningText = "Warning";
|
|
18380
|
-
warningTextStyle = styles$
|
|
18375
|
+
warningTextStyle = styles$B.warning;
|
|
18381
18376
|
} else {
|
|
18382
|
-
severityStyle = styles$
|
|
18377
|
+
severityStyle = styles$B.indicatorGuideline;
|
|
18383
18378
|
warningText = "Recommendation";
|
|
18384
|
-
warningTextStyle = styles$
|
|
18379
|
+
warningTextStyle = styles$B.warning;
|
|
18385
18380
|
}
|
|
18386
18381
|
return /*#__PURE__*/React__namespace.createElement("a", {
|
|
18387
18382
|
href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
|
|
18388
18383
|
target: "lint-help-window",
|
|
18389
18384
|
className: aphrodite.css(style)
|
|
18390
18385
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
18391
|
-
className: aphrodite.css(styles$
|
|
18386
|
+
className: aphrodite.css(styles$B.indicator, severityStyle)
|
|
18392
18387
|
}, this.props.severity === 1 && /*#__PURE__*/React__namespace.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React__namespace.createElement("div", {
|
|
18393
|
-
className: aphrodite.css(styles$
|
|
18388
|
+
className: aphrodite.css(styles$B.tooltip, tooltipAbove && styles$B.tooltipAbove)
|
|
18394
18389
|
}, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React__namespace.createElement("p", {
|
|
18395
18390
|
key: i,
|
|
18396
|
-
className: aphrodite.css(styles$
|
|
18391
|
+
className: aphrodite.css(styles$B.tooltipParagraph)
|
|
18397
18392
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
18398
18393
|
className: aphrodite.css(warningTextStyle)
|
|
18399
18394
|
}, warningText, ":", " "), m)), /*#__PURE__*/React__namespace.createElement("div", {
|
|
18400
|
-
className: aphrodite.css(styles$
|
|
18395
|
+
className: aphrodite.css(styles$B.tail, tooltipAbove && styles$B.tailAbove)
|
|
18401
18396
|
})));
|
|
18402
18397
|
};
|
|
18403
18398
|
|
|
@@ -18425,20 +18420,20 @@ class Lint extends React__namespace.Component {
|
|
|
18425
18420
|
}
|
|
18426
18421
|
if (blockHighlight) {
|
|
18427
18422
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
18428
|
-
className: aphrodite.css(styles$
|
|
18429
|
-
}, this.renderLink(styles$
|
|
18423
|
+
className: aphrodite.css(styles$B.lintContainer, styles$B.lintContainerBlock)
|
|
18424
|
+
}, this.renderLink(styles$B.radioWidgetHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
|
|
18430
18425
|
}
|
|
18431
18426
|
if (inline) {
|
|
18432
18427
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
18433
|
-
className: aphrodite.css(styles$
|
|
18434
|
-
}, this.renderLink(styles$
|
|
18428
|
+
className: aphrodite.css(styles$B.lintContainer)
|
|
18429
|
+
}, this.renderLink(styles$B.inlineHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
|
|
18435
18430
|
}
|
|
18436
18431
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
18437
|
-
className: aphrodite.css(styles$
|
|
18438
|
-
}, this.renderLink(styles$
|
|
18432
|
+
className: aphrodite.css(styles$B.lintContainer)
|
|
18433
|
+
}, this.renderLink(styles$B.hoverTarget), /*#__PURE__*/React__namespace.createElement("div", null, children));
|
|
18439
18434
|
}
|
|
18440
18435
|
}
|
|
18441
|
-
const styles$
|
|
18436
|
+
const styles$B = aphrodite.StyleSheet.create({
|
|
18442
18437
|
// This is the class of the outermost element.
|
|
18443
18438
|
// We use relative positioning so that the lint indicator can be
|
|
18444
18439
|
// positioned absolutely relative to the position of the linty container.
|
|
@@ -19132,15 +19127,17 @@ class TranslationLinter {
|
|
|
19132
19127
|
}
|
|
19133
19128
|
|
|
19134
19129
|
/**
|
|
19135
|
-
* Preprocess TeX code to convert things that
|
|
19130
|
+
* Preprocess TeX code to convert things that MathJax doesn't know how to handle
|
|
19136
19131
|
* to things is does.
|
|
19137
19132
|
*/
|
|
19138
|
-
|
|
19139
19133
|
var preprocessTex = (texCode => texCode
|
|
19140
19134
|
// Replace uses of \begin{align}...\end{align} which KaTeX doesn't
|
|
19141
19135
|
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
19142
19136
|
// the same is supported by KaTeX. It does the same for align*.
|
|
19143
19137
|
// TODO(kevinb) update content to use aligned instead of align.
|
|
19138
|
+
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
19139
|
+
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
19140
|
+
// "aligned").
|
|
19144
19141
|
.replace(/\{align[*]?\}/g, "{aligned}")
|
|
19145
19142
|
// Replace non-breaking spaces with regular spaces.
|
|
19146
19143
|
.replace(/[\u00a0]/g, " "));
|
|
@@ -20574,7 +20571,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20574
20571
|
};
|
|
20575
20572
|
const mobileInnerStyle = {
|
|
20576
20573
|
...innerStyle,
|
|
20577
|
-
...styles$
|
|
20574
|
+
...styles$A.mobileZoomableParentFix
|
|
20578
20575
|
};
|
|
20579
20576
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
20580
20577
|
key: state.key,
|
|
@@ -20608,6 +20605,9 @@ class Renderer extends React__namespace.Component {
|
|
|
20608
20605
|
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
20609
20606
|
// the same is supported by KaTeX. It does the same for align*.
|
|
20610
20607
|
// TODO(kevinb) update content to use aligned instead of align.
|
|
20608
|
+
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
20609
|
+
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
20610
|
+
// "aligned").
|
|
20611
20611
|
const tex = node.content.replace(/\{align[*]?\}/g, "{aligned}");
|
|
20612
20612
|
|
|
20613
20613
|
// We render math here instead of in perseus-markdown.jsx
|
|
@@ -20711,7 +20711,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20711
20711
|
};
|
|
20712
20712
|
const mobileInnerStyle = {
|
|
20713
20713
|
...innerStyle,
|
|
20714
|
-
...styles$
|
|
20714
|
+
...styles$A.mobileZoomableParentFix
|
|
20715
20715
|
};
|
|
20716
20716
|
const wrappedOutput = /*#__PURE__*/React__namespace.createElement("div", {
|
|
20717
20717
|
style: {
|
|
@@ -21219,7 +21219,7 @@ class Renderer extends React__namespace.Component {
|
|
|
21219
21219
|
return this.lastRenderedMarkdown;
|
|
21220
21220
|
}
|
|
21221
21221
|
}
|
|
21222
|
-
const styles$
|
|
21222
|
+
const styles$A = {
|
|
21223
21223
|
mobileZoomableParentFix: {
|
|
21224
21224
|
// NOTE(abdul): There is an issue where transform animations will
|
|
21225
21225
|
// cause the Zoomable component to disappear when running on the
|
|
@@ -22019,10 +22019,10 @@ class InputNumber extends React__namespace.Component {
|
|
|
22019
22019
|
// Note: This is _very_ similar to what `numeric-input.jsx` does. If
|
|
22020
22020
|
// you modify this, double-check if you also need to modify that
|
|
22021
22021
|
// component.
|
|
22022
|
-
const inputStyles = [styles$
|
|
22022
|
+
const inputStyles = [styles$z.default, this.props.size === "small" ? styles$z.small : null, this.props.rightAlign ? styles$z.rightAlign : styles$z.leftAlign];
|
|
22023
22023
|
// Unanswered
|
|
22024
22024
|
if (rubric && !this.props.currentValue) {
|
|
22025
|
-
inputStyles.push(styles$
|
|
22025
|
+
inputStyles.push(styles$z.answerStateUnanswered);
|
|
22026
22026
|
}
|
|
22027
22027
|
return /*#__PURE__*/React__namespace.createElement(InputWithExamples
|
|
22028
22028
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -22162,7 +22162,7 @@ class InputNumber extends React__namespace.Component {
|
|
|
22162
22162
|
return answerString;
|
|
22163
22163
|
}
|
|
22164
22164
|
}
|
|
22165
|
-
const styles$
|
|
22165
|
+
const styles$z = aphrodite.StyleSheet.create({
|
|
22166
22166
|
default: {
|
|
22167
22167
|
width: 80,
|
|
22168
22168
|
height: "auto"
|
|
@@ -23155,7 +23155,7 @@ const FocusRing = function (props) {
|
|
|
23155
23155
|
};
|
|
23156
23156
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
23157
23157
|
"data-testid": "focus-ring",
|
|
23158
|
-
className: aphrodite.css(styles$
|
|
23158
|
+
className: aphrodite.css(styles$y.ring),
|
|
23159
23159
|
style: style
|
|
23160
23160
|
}, children);
|
|
23161
23161
|
};
|
|
@@ -23164,7 +23164,7 @@ FocusRing.defaultProps = {
|
|
|
23164
23164
|
color: kaGreen$1,
|
|
23165
23165
|
multipleSelect: false
|
|
23166
23166
|
};
|
|
23167
|
-
const styles$
|
|
23167
|
+
const styles$y = aphrodite.StyleSheet.create({
|
|
23168
23168
|
ring: {
|
|
23169
23169
|
margin: "auto",
|
|
23170
23170
|
display: "inline-block",
|
|
@@ -23191,7 +23191,7 @@ function getChoiceLetter(pos, strings) {
|
|
|
23191
23191
|
}
|
|
23192
23192
|
|
|
23193
23193
|
const CHOICE_ICON_SIZE = 24;
|
|
23194
|
-
const styles$
|
|
23194
|
+
const styles$x = aphrodite.StyleSheet.create({
|
|
23195
23195
|
iconWrapper: {
|
|
23196
23196
|
display: "inline-block",
|
|
23197
23197
|
position: "relative"
|
|
@@ -23214,7 +23214,7 @@ const CrossOutLine = function (props) {
|
|
|
23214
23214
|
width: CROSS_OUT_LINE_SIZE,
|
|
23215
23215
|
height: CROSS_OUT_LINE_SIZE,
|
|
23216
23216
|
viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
|
|
23217
|
-
className: aphrodite.css(styles$
|
|
23217
|
+
className: aphrodite.css(styles$w.crossOutLine),
|
|
23218
23218
|
"data-testid": "choice-icon__cross-out-line"
|
|
23219
23219
|
}, /*#__PURE__*/React__namespace.createElement("line", {
|
|
23220
23220
|
// The line stretches from the bottom-left to top-right.
|
|
@@ -23229,7 +23229,7 @@ const CrossOutLine = function (props) {
|
|
|
23229
23229
|
strokeLinecap: "round"
|
|
23230
23230
|
}));
|
|
23231
23231
|
};
|
|
23232
|
-
const styles$
|
|
23232
|
+
const styles$w = aphrodite.StyleSheet.create({
|
|
23233
23233
|
crossOutLine: {
|
|
23234
23234
|
// Center the icon within the container.
|
|
23235
23235
|
position: "absolute",
|
|
@@ -23313,7 +23313,7 @@ const ChoiceIcon = function (props) {
|
|
|
23313
23313
|
} = props;
|
|
23314
23314
|
const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
|
|
23315
23315
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
23316
|
-
className: aphrodite.css(styles$
|
|
23316
|
+
className: aphrodite.css(styles$x.iconWrapper)
|
|
23317
23317
|
}, /*#__PURE__*/React__namespace.createElement(FocusRing, {
|
|
23318
23318
|
color: wonderBlocksTokens.color.blue,
|
|
23319
23319
|
visible: focused || hovered,
|
|
@@ -23322,13 +23322,13 @@ const ChoiceIcon = function (props) {
|
|
|
23322
23322
|
// @ts-expect-error - TS2322 - Type '{ backgroundColor: string | null | undefined; borderColor: string; color: string; borderRadius: number; }' is not assignable to type 'Properties<string | number, string & {}>'.
|
|
23323
23323
|
style: dynamicStyles,
|
|
23324
23324
|
"data-testid": "choice-icon__library-choice-icon",
|
|
23325
|
-
className: aphrodite.css(styles$
|
|
23325
|
+
className: aphrodite.css(styles$v.circle, showCorrectness && correct && styles$v.circleCorrect, showCorrectness && !correct && styles$v.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$v.circleIncorrectAnswered)
|
|
23326
23326
|
// used in BaseRadio editMode to check
|
|
23327
23327
|
// if we actually clicked on the radio icon
|
|
23328
23328
|
,
|
|
23329
23329
|
"data-is-radio-icon": true
|
|
23330
23330
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
23331
|
-
className: aphrodite.css(styles$
|
|
23331
|
+
className: aphrodite.css(styles$v.innerWrapper)
|
|
23332
23332
|
}, /*#__PURE__*/React__namespace.createElement(ChoiceInner, {
|
|
23333
23333
|
pos: pos,
|
|
23334
23334
|
showCorrectness: showCorrectness,
|
|
@@ -23337,7 +23337,7 @@ const ChoiceIcon = function (props) {
|
|
|
23337
23337
|
color: dynamicStyles.borderColor
|
|
23338
23338
|
}));
|
|
23339
23339
|
};
|
|
23340
|
-
const styles$
|
|
23340
|
+
const styles$v = aphrodite.StyleSheet.create({
|
|
23341
23341
|
innerWrapper: {
|
|
23342
23342
|
width: CHOICE_ICON_SIZE,
|
|
23343
23343
|
height: CHOICE_ICON_SIZE,
|
|
@@ -23432,19 +23432,19 @@ const OptionStatus = function (props) {
|
|
|
23432
23432
|
}
|
|
23433
23433
|
let textStyle;
|
|
23434
23434
|
if (correct) {
|
|
23435
|
-
textStyle = styles$
|
|
23435
|
+
textStyle = styles$u.correct;
|
|
23436
23436
|
} else {
|
|
23437
23437
|
if (checked || previouslyAnswered) {
|
|
23438
|
-
textStyle = styles$
|
|
23438
|
+
textStyle = styles$u.incorrectAnswered;
|
|
23439
23439
|
} else {
|
|
23440
|
-
textStyle = styles$
|
|
23440
|
+
textStyle = styles$u.incorrect;
|
|
23441
23441
|
}
|
|
23442
23442
|
}
|
|
23443
23443
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
23444
|
-
className: aphrodite.css(styles$
|
|
23444
|
+
className: aphrodite.css(styles$u.text, textStyle)
|
|
23445
23445
|
}, renderText(checked, correct, crossedOut, strings));
|
|
23446
23446
|
};
|
|
23447
|
-
const styles$
|
|
23447
|
+
const styles$u = aphrodite.StyleSheet.create({
|
|
23448
23448
|
text: {
|
|
23449
23449
|
alignItems: "center",
|
|
23450
23450
|
display: "flex",
|
|
@@ -23513,8 +23513,8 @@ const Choice = function (props) {
|
|
|
23513
23513
|
crossedOut: updatedCrossedOut
|
|
23514
23514
|
});
|
|
23515
23515
|
}
|
|
23516
|
-
const descriptionClassName = classNames__default["default"]("description", aphrodite.css(styles$
|
|
23517
|
-
const rationaleClassName = classNames__default["default"]("perseus-radio-rationale-content", aphrodite.css(styles$
|
|
23516
|
+
const descriptionClassName = classNames__default["default"]("description", aphrodite.css(styles$t.description));
|
|
23517
|
+
const rationaleClassName = classNames__default["default"]("perseus-radio-rationale-content", aphrodite.css(styles$t.rationale));
|
|
23518
23518
|
|
|
23519
23519
|
// We want to show the choices as dimmed out when the choices are disabled.
|
|
23520
23520
|
// However, we don't want to do this when we're in review mode in the
|
|
@@ -23681,7 +23681,7 @@ const Choice = function (props) {
|
|
|
23681
23681
|
"data-testid": `perseus-radio-rationale-content-${pos}`
|
|
23682
23682
|
}, rationale));
|
|
23683
23683
|
};
|
|
23684
|
-
const styles$
|
|
23684
|
+
const styles$t = aphrodite.StyleSheet.create({
|
|
23685
23685
|
description: {
|
|
23686
23686
|
display: "inline-block",
|
|
23687
23687
|
width: "100%"
|
|
@@ -23880,10 +23880,10 @@ const BaseRadio = function (props) {
|
|
|
23880
23880
|
const isMobile = apiOptions.isMobile;
|
|
23881
23881
|
const firstChoiceHighlighted = choices[0].highlighted;
|
|
23882
23882
|
const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
|
|
23883
|
-
const className = classNames__default["default"]("perseus-widget-radio", !editMode && "perseus-rendered-radio", aphrodite.css(styles$
|
|
23884
|
-
const instructionsClassName = classNames__default["default"]("instructions", aphrodite.css(styles$
|
|
23883
|
+
const className = classNames__default["default"]("perseus-widget-radio", !editMode && "perseus-rendered-radio", aphrodite.css(styles$s.radio, styles$s.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$s.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$s.radioContainerLastHighlighted));
|
|
23884
|
+
const instructionsClassName = classNames__default["default"]("instructions", aphrodite.css(styles$s.instructions, isMobile && styles$s.instructionsMobile));
|
|
23885
23885
|
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect, strings);
|
|
23886
|
-
const responsiveClassName = aphrodite.css(styles$
|
|
23886
|
+
const responsiveClassName = aphrodite.css(styles$s.responsiveFieldset);
|
|
23887
23887
|
const fieldset = /*#__PURE__*/React__namespace.createElement("fieldset", {
|
|
23888
23888
|
className: `perseus-widget-radio-fieldset ${responsiveClassName}`
|
|
23889
23889
|
}, /*#__PURE__*/React__namespace.createElement("legend", {
|
|
@@ -23934,7 +23934,7 @@ const BaseRadio = function (props) {
|
|
|
23934
23934
|
const aphroditeClassName = checked => {
|
|
23935
23935
|
// Whether or not to show correctness borders
|
|
23936
23936
|
// for this choice and the next choice.
|
|
23937
|
-
return aphrodite.css(sharedStyles.aboveScratchpad, styles$
|
|
23937
|
+
return aphrodite.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);
|
|
23938
23938
|
};
|
|
23939
23939
|
|
|
23940
23940
|
// HACK(abdulrahman): Preloads the selection-state
|
|
@@ -24008,14 +24008,14 @@ const BaseRadio = function (props) {
|
|
|
24008
24008
|
// Allow for horizontal scrolling if content is too wide, which may be
|
|
24009
24009
|
// an issue especially on phones.
|
|
24010
24010
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
24011
|
-
className: aphrodite.css(styles$
|
|
24011
|
+
className: aphrodite.css(styles$s.responsiveContainer)
|
|
24012
24012
|
}, fieldset);
|
|
24013
24013
|
};
|
|
24014
24014
|
BaseRadio.defaultProps = {
|
|
24015
24015
|
editMode: false,
|
|
24016
24016
|
multipleSelect: false
|
|
24017
24017
|
};
|
|
24018
|
-
const styles$
|
|
24018
|
+
const styles$s = aphrodite.StyleSheet.create({
|
|
24019
24019
|
instructions: {
|
|
24020
24020
|
display: "block",
|
|
24021
24021
|
color: gray17,
|
|
@@ -24699,9 +24699,9 @@ class Categorizer extends React__namespace.Component {
|
|
|
24699
24699
|
indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
|
|
24700
24700
|
}
|
|
24701
24701
|
const table = /*#__PURE__*/React__namespace.createElement("table", {
|
|
24702
|
-
className: "categorizer-table " + aphrodite.css(styles$
|
|
24702
|
+
className: "categorizer-table " + aphrodite.css(styles$r.mobileTable)
|
|
24703
24703
|
}, /*#__PURE__*/React__namespace.createElement("thead", null, /*#__PURE__*/React__namespace.createElement("tr", null, /*#__PURE__*/React__namespace.createElement("td", {
|
|
24704
|
-
className: aphrodite.css(styles$
|
|
24704
|
+
className: aphrodite.css(styles$r.emptyHeaderCell)
|
|
24705
24705
|
}), this.props.categories.map((category, i) => {
|
|
24706
24706
|
// Array index is the correct key here, as that's
|
|
24707
24707
|
// how category grading actually works -- no way
|
|
@@ -24709,7 +24709,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24709
24709
|
// middle. (If we later add that, this should be
|
|
24710
24710
|
// fixed.)
|
|
24711
24711
|
return /*#__PURE__*/React__namespace.createElement("th", {
|
|
24712
|
-
className: aphrodite.css(styles$
|
|
24712
|
+
className: aphrodite.css(styles$r.header),
|
|
24713
24713
|
key: i
|
|
24714
24714
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
24715
24715
|
content: category,
|
|
@@ -24731,7 +24731,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24731
24731
|
})), self.props.categories.map((catName, catNum) => {
|
|
24732
24732
|
const selected = self.props.values[itemNum] === catNum;
|
|
24733
24733
|
return /*#__PURE__*/React__namespace.createElement("td", {
|
|
24734
|
-
className: "category " + aphrodite.css(styles$
|
|
24734
|
+
className: "category " + aphrodite.css(styles$r.cell),
|
|
24735
24735
|
key: catNum
|
|
24736
24736
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
24737
24737
|
className: ClassNames.INTERACTIVE,
|
|
@@ -24746,7 +24746,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24746
24746
|
onChange: () => this.onChange(itemNum, catNum),
|
|
24747
24747
|
onClick: e => e.stopPropagation()
|
|
24748
24748
|
}), !isMobile && /*#__PURE__*/React__namespace.createElement("span", {
|
|
24749
|
-
className: aphrodite.css(styles$
|
|
24749
|
+
className: aphrodite.css(styles$r.radioSpan, selected && styles$r.checkedRadioSpan, this.props.static && selected && styles$r.staticCheckedRadioSpan)
|
|
24750
24750
|
}, selected ? /*#__PURE__*/React__namespace.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React__namespace.createElement(InlineIcon, iconCircleThin))));
|
|
24751
24751
|
}));
|
|
24752
24752
|
/* eslint-enable max-len */
|
|
@@ -24758,7 +24758,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24758
24758
|
"categorizer-container": true,
|
|
24759
24759
|
"static-mode": this.props.static
|
|
24760
24760
|
});
|
|
24761
|
-
const inlineStyles = this.props.apiOptions.isMobile ? [styles$
|
|
24761
|
+
const inlineStyles = this.props.apiOptions.isMobile ? [styles$r.fullBleedContainer] : [];
|
|
24762
24762
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
24763
24763
|
className: extraClassNames + " " + aphrodite.css(...inlineStyles)
|
|
24764
24764
|
}, table);
|
|
@@ -24807,7 +24807,7 @@ const pageMargin = 16;
|
|
|
24807
24807
|
|
|
24808
24808
|
// Stylesheets aren't directly testable
|
|
24809
24809
|
/* c8 ignore next */
|
|
24810
|
-
const styles$
|
|
24810
|
+
const styles$r = aphrodite.StyleSheet.create({
|
|
24811
24811
|
mobileTable: {
|
|
24812
24812
|
[mediaQueries.smOrSmaller]: {
|
|
24813
24813
|
minWidth: "auto"
|
|
@@ -25070,7 +25070,7 @@ class CSProgram extends React__namespace.Component {
|
|
|
25070
25070
|
// creator "went wild".
|
|
25071
25071
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
25072
25072
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25073
|
-
className: aphrodite.css(styles$
|
|
25073
|
+
className: aphrodite.css(styles$q.widthOverride, styleContainer && styles$q.container)
|
|
25074
25074
|
}, /*#__PURE__*/React__namespace.createElement("iframe", {
|
|
25075
25075
|
sandbox: sandboxOptions,
|
|
25076
25076
|
src: url,
|
|
@@ -25080,7 +25080,7 @@ class CSProgram extends React__namespace.Component {
|
|
|
25080
25080
|
}));
|
|
25081
25081
|
}
|
|
25082
25082
|
}
|
|
25083
|
-
const styles$
|
|
25083
|
+
const styles$q = aphrodite.StyleSheet.create({
|
|
25084
25084
|
// Override the inherited width from the perseus paragraph class
|
|
25085
25085
|
// 820 is minimum width for 420px editor and 400px canvas
|
|
25086
25086
|
widthOverride: {
|
|
@@ -25127,7 +25127,7 @@ class Definition extends React__namespace.Component {
|
|
|
25127
25127
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.Popover, {
|
|
25128
25128
|
content: /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
|
|
25129
25129
|
color: "white",
|
|
25130
|
-
style: styles$
|
|
25130
|
+
style: styles$p.tooltipBody,
|
|
25131
25131
|
closeButtonVisible: true
|
|
25132
25132
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
25133
25133
|
apiOptions: this.props.apiOptions,
|
|
@@ -25159,7 +25159,7 @@ class Definition extends React__namespace.Component {
|
|
|
25159
25159
|
});
|
|
25160
25160
|
}
|
|
25161
25161
|
}
|
|
25162
|
-
const styles$
|
|
25162
|
+
const styles$p = {
|
|
25163
25163
|
tooltipBody: {
|
|
25164
25164
|
color: wonderBlocksTokens.color.offBlack,
|
|
25165
25165
|
fontSize: 20,
|
|
@@ -25386,7 +25386,7 @@ class Explanation extends React__namespace.Component {
|
|
|
25386
25386
|
marginRight: "-6px",
|
|
25387
25387
|
"white-space": "normal"
|
|
25388
25388
|
};
|
|
25389
|
-
const contentStyling = [styles$
|
|
25389
|
+
const contentStyling = [styles$o.content, this.state.expanded ? styles$o.contentExpanded : styles$o.contentCollapsed, allowTransition && (this.state.expanded ? styles$o.transitionExpanded : styles$o.transitionCollapsed)];
|
|
25390
25390
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.UniqueIDProvider, {
|
|
25391
25391
|
mockOnFirstRender: true,
|
|
25392
25392
|
scope: "explanation-widget"
|
|
@@ -25405,7 +25405,7 @@ class Explanation extends React__namespace.Component {
|
|
|
25405
25405
|
"aria-hidden": !this.state.expanded,
|
|
25406
25406
|
testId: "content-container"
|
|
25407
25407
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
25408
|
-
style: styles$
|
|
25408
|
+
style: styles$o.contentWrapper
|
|
25409
25409
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
25410
25410
|
apiOptions: this.props.apiOptions,
|
|
25411
25411
|
content: this.props.explanation,
|
|
@@ -25424,7 +25424,7 @@ class Explanation extends React__namespace.Component {
|
|
|
25424
25424
|
const leftBorderSpacing = 23;
|
|
25425
25425
|
const verticalContentPadding = 10;
|
|
25426
25426
|
const arrowHeight = 14;
|
|
25427
|
-
const styles$
|
|
25427
|
+
const styles$o = aphrodite.StyleSheet.create({
|
|
25428
25428
|
content: {
|
|
25429
25429
|
borderLeft: "0px solid #ccc",
|
|
25430
25430
|
display: "inline-grid",
|
|
@@ -25490,15 +25490,15 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
25490
25490
|
nextQuestion
|
|
25491
25491
|
} = this.context.strings;
|
|
25492
25492
|
const answerBarStyle = {
|
|
25493
|
-
...styles$
|
|
25493
|
+
...styles$n.answerBar,
|
|
25494
25494
|
backgroundColor: answerBarState === "CORRECT" ? wonderBlocksTokens.color.offWhite : "white",
|
|
25495
25495
|
// Center the "Correct!" message only when there's no next question
|
|
25496
25496
|
justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
|
|
25497
25497
|
};
|
|
25498
25498
|
const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React__namespace.createElement("span", {
|
|
25499
|
-
style: styles$
|
|
25499
|
+
style: styles$n.text
|
|
25500
25500
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
25501
|
-
style: styles$
|
|
25501
|
+
style: styles$n.tryAgainIcon
|
|
25502
25502
|
}, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React__namespace.createElement("span", {
|
|
25503
25503
|
style: {
|
|
25504
25504
|
marginLeft: 8
|
|
@@ -25517,7 +25517,7 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
25517
25517
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25518
25518
|
style: answerBarStyle
|
|
25519
25519
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
25520
|
-
style: styles$
|
|
25520
|
+
style: styles$n.text
|
|
25521
25521
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
25522
25522
|
style: {
|
|
25523
25523
|
fontSize: 28,
|
|
@@ -25539,7 +25539,7 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
25539
25539
|
}
|
|
25540
25540
|
}
|
|
25541
25541
|
const fontSize = 17;
|
|
25542
|
-
const styles$
|
|
25542
|
+
const styles$n = {
|
|
25543
25543
|
answerBar: {
|
|
25544
25544
|
display: "flex",
|
|
25545
25545
|
alignItems: "center",
|
|
@@ -25739,7 +25739,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25739
25739
|
}));
|
|
25740
25740
|
gradeStatus = this.context.strings.incorrect;
|
|
25741
25741
|
}
|
|
25742
|
-
const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$
|
|
25742
|
+
const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$m.gradedGroupInSet) : aphrodite.css(styles$m.gradedGroup);
|
|
25743
25743
|
const classes = classNames__default["default"]({
|
|
25744
25744
|
[mobileClass]: apiOptions.isMobile,
|
|
25745
25745
|
"perseus-graded-group": true,
|
|
@@ -25758,7 +25758,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25758
25758
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25759
25759
|
className: classes
|
|
25760
25760
|
}, !!this.props.title && /*#__PURE__*/React__namespace.createElement("div", {
|
|
25761
|
-
className: aphrodite.css(styles$
|
|
25761
|
+
className: aphrodite.css(styles$m.title)
|
|
25762
25762
|
}, this.props.title), /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, this.props, {
|
|
25763
25763
|
// eslint-disable-next-line react/no-string-refs
|
|
25764
25764
|
ref: "renderer",
|
|
@@ -25792,7 +25792,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25792
25792
|
}, this.context.strings.nextQuestion), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("button", {
|
|
25793
25793
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
25794
25794
|
tabIndex: "0",
|
|
25795
|
-
className: aphrodite.css(styles$
|
|
25795
|
+
className: aphrodite.css(styles$m.explanationTitle),
|
|
25796
25796
|
onClick: () => this.setState({
|
|
25797
25797
|
showHint: false
|
|
25798
25798
|
}),
|
|
@@ -25825,7 +25825,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25825
25825
|
showHint: true
|
|
25826
25826
|
});
|
|
25827
25827
|
},
|
|
25828
|
-
className: aphrodite.css(styles$
|
|
25828
|
+
className: aphrodite.css(styles$m.showHintLink)
|
|
25829
25829
|
}, this.context.strings.explain)), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React__namespace.createElement(GradedGroupAnswerBar, {
|
|
25830
25830
|
apiOptions: apiOptions,
|
|
25831
25831
|
answerBarState: answerBarState,
|
|
@@ -25837,7 +25837,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25837
25837
|
const traverseChildWidgets$2 = function (props, traverseRenderer) {
|
|
25838
25838
|
return ___default["default"].extend({}, props, traverseRenderer(props));
|
|
25839
25839
|
};
|
|
25840
|
-
const styles$
|
|
25840
|
+
const styles$m = aphrodite.StyleSheet.create({
|
|
25841
25841
|
gradedGroupInSet: {
|
|
25842
25842
|
// Reset a few desktop-only styles that come from graded-group.less
|
|
25843
25843
|
marginLeft: 0,
|
|
@@ -25908,20 +25908,20 @@ class Indicators extends React__namespace.Component {
|
|
|
25908
25908
|
return /*#__PURE__*/React__namespace.createElement("ul", {
|
|
25909
25909
|
// reduntantly add class name for use in .less files--
|
|
25910
25910
|
// the styles object key gets hashed
|
|
25911
|
-
className: classNames__default["default"](aphrodite.css(styles$
|
|
25911
|
+
className: classNames__default["default"](aphrodite.css(styles$l.indicatorContainer), "indicatorContainer")
|
|
25912
25912
|
}, this.props.gradedGroups.map((_ref, i) => {
|
|
25913
25913
|
let {
|
|
25914
25914
|
title
|
|
25915
25915
|
} = _ref;
|
|
25916
25916
|
return /*#__PURE__*/React__namespace.createElement("li", {
|
|
25917
|
-
className: aphrodite.css(styles$
|
|
25917
|
+
className: aphrodite.css(styles$l.indicator),
|
|
25918
25918
|
key: title
|
|
25919
25919
|
}, /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
25920
25920
|
role: "button",
|
|
25921
25921
|
"aria-label": this.context.strings.skipToTitle({
|
|
25922
25922
|
title
|
|
25923
25923
|
}),
|
|
25924
|
-
style: styles$
|
|
25924
|
+
style: styles$l.indicatorButton,
|
|
25925
25925
|
onClick: () => this.props.onChangeCurrentGroup(i),
|
|
25926
25926
|
onKeyDown: e => this.handleKeyDown(e, i)
|
|
25927
25927
|
}, _ref2 => {
|
|
@@ -25931,9 +25931,9 @@ class Indicators extends React__namespace.Component {
|
|
|
25931
25931
|
pressed
|
|
25932
25932
|
} = _ref2;
|
|
25933
25933
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
25934
|
-
style: [styles$
|
|
25934
|
+
style: [styles$l.indicatorDot, (hovered || focused || pressed) && styles$l.indicatorDotFocused]
|
|
25935
25935
|
}, i === this.props.currentGroup && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
25936
|
-
style: styles$
|
|
25936
|
+
style: styles$l.indicatorDotActive
|
|
25937
25937
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
25938
25938
|
className: aphrodite.css(a11y.srOnly)
|
|
25939
25939
|
}, this.context.strings.current)));
|
|
@@ -26009,7 +26009,7 @@ class GradedGroupSet extends React__namespace.Component {
|
|
|
26009
26009
|
} = getDependencies();
|
|
26010
26010
|
if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
|
|
26011
26011
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
26012
|
-
className: aphrodite.css(styles$
|
|
26012
|
+
className: aphrodite.css(styles$l.container)
|
|
26013
26013
|
}, this.props.gradedGroups.map((gradedGroup, i) => {
|
|
26014
26014
|
return (
|
|
26015
26015
|
/*#__PURE__*/
|
|
@@ -26032,13 +26032,13 @@ class GradedGroupSet extends React__namespace.Component {
|
|
|
26032
26032
|
const numGroups = this.props.gradedGroups.length;
|
|
26033
26033
|
const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
|
|
26034
26034
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
26035
|
-
className: aphrodite.css(styles$
|
|
26035
|
+
className: aphrodite.css(styles$l.container)
|
|
26036
26036
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
26037
|
-
className: aphrodite.css(styles$
|
|
26037
|
+
className: aphrodite.css(styles$l.top)
|
|
26038
26038
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
26039
|
-
className: aphrodite.css(styles$
|
|
26039
|
+
className: aphrodite.css(styles$l.title)
|
|
26040
26040
|
}, currentGroup.title), /*#__PURE__*/React__namespace.createElement("div", {
|
|
26041
|
-
className: aphrodite.css(styles$
|
|
26041
|
+
className: aphrodite.css(styles$l.spacer)
|
|
26042
26042
|
}), /*#__PURE__*/React__namespace.createElement(Indicators, {
|
|
26043
26043
|
currentGroup: this.state.currentGroup,
|
|
26044
26044
|
gradedGroups: this.props.gradedGroups,
|
|
@@ -26076,7 +26076,7 @@ var GradedGroupSet$1 = {
|
|
|
26076
26076
|
tracking: "all",
|
|
26077
26077
|
isLintable: true
|
|
26078
26078
|
};
|
|
26079
|
-
const styles$
|
|
26079
|
+
const styles$l = aphrodite.StyleSheet.create({
|
|
26080
26080
|
top: {
|
|
26081
26081
|
display: "flex",
|
|
26082
26082
|
flexDirection: "row"
|
|
@@ -26182,7 +26182,7 @@ class ButtonGroup extends React__namespace.Component {
|
|
|
26182
26182
|
id: "" + i,
|
|
26183
26183
|
ref: "button" + i,
|
|
26184
26184
|
key: "" + i,
|
|
26185
|
-
className: aphrodite.css(styles$
|
|
26185
|
+
className: aphrodite.css(styles$k.buttonStyle, button.value === value && styles$k.selectedStyle),
|
|
26186
26186
|
onClick: () => this.toggleSelect(button.value)
|
|
26187
26187
|
}, button.content || "" + button.value);
|
|
26188
26188
|
});
|
|
@@ -26195,7 +26195,7 @@ class ButtonGroup extends React__namespace.Component {
|
|
|
26195
26195
|
}, buttons);
|
|
26196
26196
|
}
|
|
26197
26197
|
}
|
|
26198
|
-
const styles$
|
|
26198
|
+
const styles$k = aphrodite.StyleSheet.create({
|
|
26199
26199
|
buttonStyle: {
|
|
26200
26200
|
backgroundColor: "white",
|
|
26201
26201
|
border: "1px solid #ccc",
|
|
@@ -26799,7 +26799,7 @@ var util = /*#__PURE__*/Object.freeze({
|
|
|
26799
26799
|
});
|
|
26800
26800
|
|
|
26801
26801
|
// @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
|
|
26802
|
-
const MovablePoint$
|
|
26802
|
+
const MovablePoint$3 = Graphie.MovablePoint;
|
|
26803
26803
|
// @ts-expect-error - TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
26804
26804
|
const MovableLine$2 = Graphie.MovableLine;
|
|
26805
26805
|
function isFlipped(newCoord, oldCoord, line) {
|
|
@@ -26845,7 +26845,7 @@ class FunctionGrapher extends React__namespace.Component {
|
|
|
26845
26845
|
})();
|
|
26846
26846
|
render() {
|
|
26847
26847
|
const pointForCoord = (coord, i) => {
|
|
26848
|
-
return /*#__PURE__*/React__namespace.createElement(MovablePoint$
|
|
26848
|
+
return /*#__PURE__*/React__namespace.createElement(MovablePoint$3, {
|
|
26849
26849
|
key: i,
|
|
26850
26850
|
coord: coord,
|
|
26851
26851
|
static: this.props.static,
|
|
@@ -26982,7 +26982,7 @@ class FunctionGrapher extends React__namespace.Component {
|
|
|
26982
26982
|
}],
|
|
26983
26983
|
normalStyle: dashed,
|
|
26984
26984
|
highlightStyle: dashed
|
|
26985
|
-
}, ___default["default"].map(asymptote, (coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$
|
|
26985
|
+
}, ___default["default"].map(asymptote, (coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$3, {
|
|
26986
26986
|
key: `asymptoteCoord-${i}`,
|
|
26987
26987
|
coord: coord,
|
|
26988
26988
|
static: true,
|
|
@@ -27723,7 +27723,7 @@ const Label = Graphie.Label;
|
|
|
27723
27723
|
// @ts-expect-error - TS2339 - Property 'Line' does not exist on type 'typeof Graphie'.
|
|
27724
27724
|
const Line$2 = Graphie.Line;
|
|
27725
27725
|
// @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
|
|
27726
|
-
const MovablePoint$
|
|
27726
|
+
const MovablePoint$2 = Graphie.MovablePoint;
|
|
27727
27727
|
// @ts-expect-error - TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
27728
27728
|
const MovableLine$1 = Graphie.MovableLine;
|
|
27729
27729
|
// @ts-expect-error - TS2339 - Property 'Plot' does not exist on type 'typeof Graphie'.
|
|
@@ -27977,7 +27977,7 @@ class Interaction extends React__namespace.Component {
|
|
|
27977
27977
|
return [coordX, coordY];
|
|
27978
27978
|
}];
|
|
27979
27979
|
if (element.options.constraint === "snap") {
|
|
27980
|
-
constraints.push(MovablePoint$
|
|
27980
|
+
constraints.push(MovablePoint$2.constraints.snap(element.options.snap));
|
|
27981
27981
|
} else if (element.options.constraint === "x") {
|
|
27982
27982
|
constraints.push(coord => {
|
|
27983
27983
|
return [
|
|
@@ -27999,7 +27999,7 @@ class Interaction extends React__namespace.Component {
|
|
|
27999
27999
|
// TODO(eater): foo_[xyz] are hacky non-props to
|
|
28000
28000
|
// get the component to update when constraints
|
|
28001
28001
|
// change
|
|
28002
|
-
return /*#__PURE__*/React__namespace.createElement(MovablePoint$
|
|
28002
|
+
return /*#__PURE__*/React__namespace.createElement(MovablePoint$2, {
|
|
28003
28003
|
key: element.key,
|
|
28004
28004
|
coord: [
|
|
28005
28005
|
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
@@ -28034,7 +28034,7 @@ class Interaction extends React__namespace.Component {
|
|
|
28034
28034
|
return [coordX, coordY];
|
|
28035
28035
|
}];
|
|
28036
28036
|
if (element.options.constraint === "snap") {
|
|
28037
|
-
constraints.push(MovablePoint$
|
|
28037
|
+
constraints.push(MovablePoint$2.constraints.snap(element.options.snap));
|
|
28038
28038
|
} else if (element.options.constraint === "x") {
|
|
28039
28039
|
constraints.push(coord => {
|
|
28040
28040
|
return [
|
|
@@ -28075,14 +28075,14 @@ class Interaction extends React__namespace.Component {
|
|
|
28075
28075
|
foo_x: element.options.constraint,
|
|
28076
28076
|
foo_y: element.options.constraintFn,
|
|
28077
28077
|
foo_z: element.options.snap
|
|
28078
|
-
}, /*#__PURE__*/React__namespace.createElement(MovablePoint$
|
|
28078
|
+
}, /*#__PURE__*/React__namespace.createElement(MovablePoint$2, {
|
|
28079
28079
|
coord: start,
|
|
28080
28080
|
static: true,
|
|
28081
28081
|
normalStyle: {
|
|
28082
28082
|
stroke: "none",
|
|
28083
28083
|
fill: "none"
|
|
28084
28084
|
}
|
|
28085
|
-
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$
|
|
28085
|
+
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$2, {
|
|
28086
28086
|
coord: end,
|
|
28087
28087
|
static: true,
|
|
28088
28088
|
normalStyle: {
|
|
@@ -28639,7 +28639,7 @@ const defaultGraphConfig = {
|
|
|
28639
28639
|
width: 0,
|
|
28640
28640
|
height: 0,
|
|
28641
28641
|
labels: [],
|
|
28642
|
-
|
|
28642
|
+
disableKeyboardInteraction: false
|
|
28643
28643
|
};
|
|
28644
28644
|
const GraphConfigContext = /*#__PURE__*/React.createContext(defaultGraphConfig);
|
|
28645
28645
|
function useGraphConfig() {
|
|
@@ -28786,6 +28786,30 @@ const segmentsIntersect = (_ref, _ref2) => {
|
|
|
28786
28786
|
}
|
|
28787
28787
|
};
|
|
28788
28788
|
|
|
28789
|
+
// Finds the unique intersection point between two rays. Returns undefined if
|
|
28790
|
+
// there is not exactly one intersection point. The first point in each of the
|
|
28791
|
+
// given ray "segments" should be the initial point of the ray. The second point
|
|
28792
|
+
// can be any arbitrary point on the ray different from the initial point.
|
|
28793
|
+
function findIntersectionOfRays(_ref3, _ref4) {
|
|
28794
|
+
let [[a, b], [c, d]] = _ref3;
|
|
28795
|
+
let [[p, q], [r, s]] = _ref4;
|
|
28796
|
+
// See https://stackoverflow.com/a/24392281/7347484 for an explanation of
|
|
28797
|
+
// the determinant and lambda values.
|
|
28798
|
+
const determinant = (c - a) * (s - q) - (r - p) * (d - b);
|
|
28799
|
+
if (determinant === 0) {
|
|
28800
|
+
return undefined;
|
|
28801
|
+
} else {
|
|
28802
|
+
const lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / determinant;
|
|
28803
|
+
const gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / determinant;
|
|
28804
|
+
if (lambda <= 0 || gamma >= 1) {
|
|
28805
|
+
return undefined;
|
|
28806
|
+
}
|
|
28807
|
+
const initialPoint = [a, b];
|
|
28808
|
+
const direction = mafs.vec.sub([c, d], initialPoint);
|
|
28809
|
+
return mafs.vec.add(initialPoint, mafs.vec.scale(direction, lambda));
|
|
28810
|
+
}
|
|
28811
|
+
}
|
|
28812
|
+
|
|
28789
28813
|
// This file contains helper functions for working with angles.
|
|
28790
28814
|
|
|
28791
28815
|
function convertDegreesToRadians(degrees) {
|
|
@@ -28798,6 +28822,8 @@ function calculateAngleInDegrees(_ref) {
|
|
|
28798
28822
|
let [x, y] = _ref;
|
|
28799
28823
|
return Math.atan2(y, x) * 180 / Math.PI;
|
|
28800
28824
|
}
|
|
28825
|
+
|
|
28826
|
+
// Converts polar coordinates to cartesian. The th(eta) parameter is in degrees.
|
|
28801
28827
|
function polar(r, th) {
|
|
28802
28828
|
if (typeof r === "number") {
|
|
28803
28829
|
r = [r, r];
|
|
@@ -29407,7 +29433,7 @@ const VisibleIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
|
29407
29433
|
width: "24",
|
|
29408
29434
|
height: "24",
|
|
29409
29435
|
viewBox: "0 0 24 24",
|
|
29410
|
-
className: aphrodite.css(styles$
|
|
29436
|
+
className: aphrodite.css(styles$j.icon)
|
|
29411
29437
|
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
29412
29438
|
id: "a",
|
|
29413
29439
|
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"
|
|
@@ -29438,7 +29464,7 @@ const HiddenIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
|
29438
29464
|
width: "24",
|
|
29439
29465
|
height: "24",
|
|
29440
29466
|
viewBox: "0 0 24 24",
|
|
29441
|
-
className: aphrodite.css(styles$
|
|
29467
|
+
className: aphrodite.css(styles$j.icon)
|
|
29442
29468
|
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
29443
29469
|
id: "a",
|
|
29444
29470
|
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"
|
|
@@ -29473,20 +29499,20 @@ const HUD = _ref => {
|
|
|
29473
29499
|
let state;
|
|
29474
29500
|
let icon;
|
|
29475
29501
|
if (enabled) {
|
|
29476
|
-
state = styles$
|
|
29502
|
+
state = styles$j.enabled;
|
|
29477
29503
|
icon = /*#__PURE__*/React__namespace.createElement(VisibleIcon, null);
|
|
29478
29504
|
} else {
|
|
29479
|
-
state = styles$
|
|
29505
|
+
state = styles$j.disabled;
|
|
29480
29506
|
icon = /*#__PURE__*/React__namespace.createElement(HiddenIcon, null);
|
|
29481
29507
|
}
|
|
29482
29508
|
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
29483
|
-
className: aphrodite.css(styles$
|
|
29509
|
+
className: aphrodite.css(styles$j.hud, fixedPosition && styles$j.hudFixedPosition, state),
|
|
29484
29510
|
onClick: e => {
|
|
29485
29511
|
onClick();
|
|
29486
29512
|
}
|
|
29487
29513
|
}, icon, message);
|
|
29488
29514
|
};
|
|
29489
|
-
const styles$
|
|
29515
|
+
const styles$j = aphrodite.StyleSheet.create({
|
|
29490
29516
|
hud: {
|
|
29491
29517
|
boxSizing: "border-box",
|
|
29492
29518
|
height: 36,
|
|
@@ -29536,19 +29562,19 @@ const styles$k = aphrodite.StyleSheet.create({
|
|
|
29536
29562
|
}
|
|
29537
29563
|
});
|
|
29538
29564
|
|
|
29539
|
-
const
|
|
29565
|
+
const InfoTipBase = props => {
|
|
29540
29566
|
return /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
29541
29567
|
content: /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.Body, {
|
|
29542
|
-
style: styles$
|
|
29568
|
+
style: styles$i.body
|
|
29543
29569
|
}, props.children),
|
|
29544
29570
|
placement: "right"
|
|
29545
29571
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksIcon.PhosphorIcon, {
|
|
29546
29572
|
size: "small",
|
|
29547
29573
|
icon: questionIcon__default["default"],
|
|
29548
|
-
style: styles$
|
|
29574
|
+
style: styles$i.spacingLeft
|
|
29549
29575
|
}));
|
|
29550
29576
|
};
|
|
29551
|
-
const styles$
|
|
29577
|
+
const styles$i = aphrodite.StyleSheet.create({
|
|
29552
29578
|
spacingLeft: {
|
|
29553
29579
|
marginInlineStart: wonderBlocksTokens.spacing.xxxSmall_4
|
|
29554
29580
|
},
|
|
@@ -29577,7 +29603,7 @@ class InfoTip extends React__namespace.Component {
|
|
|
29577
29603
|
|
|
29578
29604
|
render() {
|
|
29579
29605
|
if (this.state.didMount) {
|
|
29580
|
-
return /*#__PURE__*/React__namespace.createElement(
|
|
29606
|
+
return /*#__PURE__*/React__namespace.createElement(InfoTipBase, this.props);
|
|
29581
29607
|
}
|
|
29582
29608
|
return /*#__PURE__*/React__namespace.createElement("div", null);
|
|
29583
29609
|
}
|
|
@@ -29624,7 +29650,7 @@ class MultiButtonGroup extends React__namespace.Component {
|
|
|
29624
29650
|
id: "" + i,
|
|
29625
29651
|
key: "" + i,
|
|
29626
29652
|
ref: "button" + i,
|
|
29627
|
-
className: aphrodite.css(styles$
|
|
29653
|
+
className: aphrodite.css(styles$h.buttonStyle, selected && styles$h.selectedStyle),
|
|
29628
29654
|
onClick: () => this.toggleSelect(button.value)
|
|
29629
29655
|
}, button.content || "" + button.value);
|
|
29630
29656
|
});
|
|
@@ -29636,7 +29662,7 @@ class MultiButtonGroup extends React__namespace.Component {
|
|
|
29636
29662
|
}, buttons);
|
|
29637
29663
|
}
|
|
29638
29664
|
}
|
|
29639
|
-
const styles$
|
|
29665
|
+
const styles$h = aphrodite.StyleSheet.create({
|
|
29640
29666
|
buttonStyle: {
|
|
29641
29667
|
backgroundColor: "white",
|
|
29642
29668
|
border: "1px solid #ccc",
|
|
@@ -29868,62 +29894,6 @@ class NumberInput extends React__namespace.Component {
|
|
|
29868
29894
|
};
|
|
29869
29895
|
}
|
|
29870
29896
|
|
|
29871
|
-
/* eslint-disable @babel/no-invalid-this */
|
|
29872
|
-
|
|
29873
|
-
/* A checkbox that syncs its value to props using the
|
|
29874
|
-
* renderer's onChange method, and gets the prop name
|
|
29875
|
-
* dynamically from its props list
|
|
29876
|
-
*/
|
|
29877
|
-
const PropCheckBox = createReactClass__default["default"]({
|
|
29878
|
-
displayName: "PropCheckBox",
|
|
29879
|
-
propTypes: {
|
|
29880
|
-
labelAlignment: PropTypes__default["default"].oneOf(["left", "right"])
|
|
29881
|
-
},
|
|
29882
|
-
DEFAULT_PROPS: {
|
|
29883
|
-
label: null,
|
|
29884
|
-
onChange: null,
|
|
29885
|
-
labelAlignment: "left"
|
|
29886
|
-
},
|
|
29887
|
-
getDefaultProps: function () {
|
|
29888
|
-
return this.DEFAULT_PROPS;
|
|
29889
|
-
},
|
|
29890
|
-
propName: function () {
|
|
29891
|
-
const propName = ___default["default"].find(___default["default"].keys(this.props), function (localPropName) {
|
|
29892
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
29893
|
-
return !___default["default"].has(this.DEFAULT_PROPS, localPropName);
|
|
29894
|
-
}, this);
|
|
29895
|
-
if (!propName) {
|
|
29896
|
-
throw new perseusCore.PerseusError("Attempted to create a PropCheckBox with no prop!", perseusCore.Errors.InvalidInput);
|
|
29897
|
-
}
|
|
29898
|
-
return propName;
|
|
29899
|
-
},
|
|
29900
|
-
_labelAlignLeft: function () {
|
|
29901
|
-
return this.props.labelAlignment === "left";
|
|
29902
|
-
},
|
|
29903
|
-
render: function () {
|
|
29904
|
-
const propName = this.propName();
|
|
29905
|
-
return /*#__PURE__*/React__namespace.createElement("label", {
|
|
29906
|
-
className: aphrodite.css(styles$h.labeledCheckbox)
|
|
29907
|
-
}, this._labelAlignLeft() && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, null, this.props.label), /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
|
|
29908
|
-
checked: this.props[propName],
|
|
29909
|
-
onChange: this.toggle
|
|
29910
|
-
}), !this._labelAlignLeft() && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, null, this.props.label));
|
|
29911
|
-
},
|
|
29912
|
-
toggle: function () {
|
|
29913
|
-
const propName = this.propName();
|
|
29914
|
-
const changes = {};
|
|
29915
|
-
changes[propName] = !this.props[propName];
|
|
29916
|
-
this.props.onChange(changes);
|
|
29917
|
-
}
|
|
29918
|
-
});
|
|
29919
|
-
const styles$h = aphrodite.StyleSheet.create({
|
|
29920
|
-
labeledCheckbox: {
|
|
29921
|
-
display: "flex",
|
|
29922
|
-
flexDirection: "row",
|
|
29923
|
-
alignItems: "center"
|
|
29924
|
-
}
|
|
29925
|
-
});
|
|
29926
|
-
|
|
29927
29897
|
const truth = () => true;
|
|
29928
29898
|
|
|
29929
29899
|
/* A minor abstraction on top of NumberInput for ranges
|
|
@@ -29982,7 +29952,6 @@ var components = /*#__PURE__*/Object.freeze({
|
|
|
29982
29952
|
MathInput: MathInput,
|
|
29983
29953
|
MultiButtonGroup: MultiButtonGroup,
|
|
29984
29954
|
NumberInput: NumberInput,
|
|
29985
|
-
PropCheckBox: PropCheckBox,
|
|
29986
29955
|
RangeInput: RangeInput,
|
|
29987
29956
|
SvgImage: SvgImage,
|
|
29988
29957
|
TextInput: TextInput,
|
|
@@ -30140,8 +30109,9 @@ const lockedFigureColors = {
|
|
|
30140
30109
|
};
|
|
30141
30110
|
const lockedFigureFillStyles = {
|
|
30142
30111
|
none: 0,
|
|
30143
|
-
|
|
30144
|
-
translucent: 0.4
|
|
30112
|
+
white: 1,
|
|
30113
|
+
translucent: 0.4,
|
|
30114
|
+
solid: 1
|
|
30145
30115
|
};
|
|
30146
30116
|
const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
|
|
30147
30117
|
|
|
@@ -30161,10 +30131,20 @@ const LockedEllipse = props => {
|
|
|
30161
30131
|
fillOpacity: lockedFigureFillStyles[fillStyle],
|
|
30162
30132
|
strokeStyle: strokeStyle,
|
|
30163
30133
|
color: lockedFigureColors[color]
|
|
30134
|
+
// We need to override the svg props if we want to have a
|
|
30135
|
+
// different fill color than the stroke color (specifically,
|
|
30136
|
+
// in the case where the fillStyle is "white").
|
|
30137
|
+
,
|
|
30138
|
+
svgEllipseProps: {
|
|
30139
|
+
style: {
|
|
30140
|
+
fill: fillStyle === "white" ? wonderBlocksTokens.color.white : lockedFigureColors[color]
|
|
30141
|
+
}
|
|
30142
|
+
}
|
|
30164
30143
|
});
|
|
30165
30144
|
};
|
|
30166
30145
|
|
|
30167
30146
|
const LockedFunction = props => {
|
|
30147
|
+
const [equation, setEquation] = React.useState();
|
|
30168
30148
|
const {
|
|
30169
30149
|
color,
|
|
30170
30150
|
strokeStyle,
|
|
@@ -30176,7 +30156,14 @@ const LockedFunction = props => {
|
|
|
30176
30156
|
style: strokeStyle,
|
|
30177
30157
|
domain
|
|
30178
30158
|
};
|
|
30179
|
-
|
|
30159
|
+
React.useEffect(() => {
|
|
30160
|
+
// Parsing the equation in a "useEffect" hook saves about 2ms each frame
|
|
30161
|
+
// when the learner is interacting with the graph (i.e. moving points).
|
|
30162
|
+
setEquation(KAS__namespace.parse(props.equation).expr);
|
|
30163
|
+
}, [props.equation]);
|
|
30164
|
+
if (typeof equation === "undefined") {
|
|
30165
|
+
return null;
|
|
30166
|
+
}
|
|
30180
30167
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
30181
30168
|
className: "locked-function"
|
|
30182
30169
|
}, directionalAxis === "x" && /*#__PURE__*/React__namespace.createElement(mafs.Plot.OfX, _extends({
|
|
@@ -30379,6 +30366,15 @@ const LockedPolygon = props => {
|
|
|
30379
30366
|
fillOpacity: lockedFigureFillStyles[fillStyle],
|
|
30380
30367
|
strokeStyle: strokeStyle,
|
|
30381
30368
|
color: lockedFigureColors[color]
|
|
30369
|
+
// We need to override the svg props if we want to have a
|
|
30370
|
+
// different fill color than the stroke color (specifically,
|
|
30371
|
+
// in the case where the fillStyle is "white").
|
|
30372
|
+
,
|
|
30373
|
+
svgPolygonProps: {
|
|
30374
|
+
style: {
|
|
30375
|
+
fill: fillStyle === "white" ? wonderBlocksTokens.color.white : lockedFigureColors[color]
|
|
30376
|
+
}
|
|
30377
|
+
}
|
|
30382
30378
|
}), showVertices && points.map((point, index) => /*#__PURE__*/React__namespace.createElement(mafs.Point, {
|
|
30383
30379
|
key: `locked-polygon-point-${index}`,
|
|
30384
30380
|
x: point[X],
|
|
@@ -30625,7 +30621,7 @@ function useDraggable(args) {
|
|
|
30625
30621
|
gestureTarget: target,
|
|
30626
30622
|
onMove,
|
|
30627
30623
|
point,
|
|
30628
|
-
|
|
30624
|
+
constrainKeyboardMovement
|
|
30629
30625
|
} = args;
|
|
30630
30626
|
const [dragging, setDragging] = React__namespace.useState(false);
|
|
30631
30627
|
const {
|
|
@@ -30648,6 +30644,7 @@ function useDraggable(args) {
|
|
|
30648
30644
|
event?.stopPropagation();
|
|
30649
30645
|
const isKeyboard = type.includes("key");
|
|
30650
30646
|
if (isKeyboard) {
|
|
30647
|
+
invariant(event instanceof KeyboardEvent);
|
|
30651
30648
|
event?.preventDefault();
|
|
30652
30649
|
|
|
30653
30650
|
// When a key is held down, we see multiple "keydown" events,
|
|
@@ -30659,6 +30656,11 @@ function useDraggable(args) {
|
|
|
30659
30656
|
if (type === "keyup") {
|
|
30660
30657
|
return;
|
|
30661
30658
|
}
|
|
30659
|
+
if (typeof constrainKeyboardMovement === "object") {
|
|
30660
|
+
const destination = constrainKeyboardMovement[directionForKey[event.key]];
|
|
30661
|
+
onMove(destination ?? point);
|
|
30662
|
+
return;
|
|
30663
|
+
}
|
|
30662
30664
|
const {
|
|
30663
30665
|
direction: yDownDirection,
|
|
30664
30666
|
altKey,
|
|
@@ -30679,7 +30681,7 @@ function useDraggable(args) {
|
|
|
30679
30681
|
for (const dx of tests) {
|
|
30680
30682
|
// Transform the test back into the point's coordinate system
|
|
30681
30683
|
const testMovement = mafs.vec.scale(direction, dx);
|
|
30682
|
-
const testPoint =
|
|
30684
|
+
const testPoint = constrainKeyboardMovement(mafs.vec.transform(mafs.vec.add(mafs.vec.transform(point, userTransform), testMovement), inverseTransform));
|
|
30683
30685
|
if (mafs.vec.dist(testPoint, point) > min) {
|
|
30684
30686
|
onMove(testPoint);
|
|
30685
30687
|
break;
|
|
@@ -30699,7 +30701,7 @@ function useDraggable(args) {
|
|
|
30699
30701
|
return;
|
|
30700
30702
|
}
|
|
30701
30703
|
const movement = mafs.vec.transform(pixelMovement, inverseViewTransform);
|
|
30702
|
-
onMove(
|
|
30704
|
+
onMove(mafs.vec.transform(mafs.vec.add(pickup.current, movement), inverseTransform));
|
|
30703
30705
|
}
|
|
30704
30706
|
}, {
|
|
30705
30707
|
target,
|
|
@@ -30711,6 +30713,12 @@ function useDraggable(args) {
|
|
|
30711
30713
|
dragging
|
|
30712
30714
|
};
|
|
30713
30715
|
}
|
|
30716
|
+
const directionForKey = {
|
|
30717
|
+
ArrowLeft: "left",
|
|
30718
|
+
ArrowRight: "right",
|
|
30719
|
+
ArrowUp: "up",
|
|
30720
|
+
ArrowDown: "down"
|
|
30721
|
+
};
|
|
30714
30722
|
function getInverseTransform(transform) {
|
|
30715
30723
|
const invert = mafs.vec.matrixInvert(transform);
|
|
30716
30724
|
invariant(invert !== null, "Could not invert transform matrix. A parent transformation matrix might be degenerative (mapping 2D space to a line).");
|
|
@@ -30760,7 +30768,7 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
30760
30768
|
range,
|
|
30761
30769
|
markings,
|
|
30762
30770
|
showTooltips,
|
|
30763
|
-
|
|
30771
|
+
disableKeyboardInteraction
|
|
30764
30772
|
} = useGraphConfig();
|
|
30765
30773
|
const {
|
|
30766
30774
|
point,
|
|
@@ -30805,7 +30813,7 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
30805
30813
|
cursor
|
|
30806
30814
|
},
|
|
30807
30815
|
"data-testid": "movable-point",
|
|
30808
|
-
tabIndex:
|
|
30816
|
+
tabIndex: disableKeyboardInteraction ? -1 : tabIndex(focusBehavior)
|
|
30809
30817
|
}, /*#__PURE__*/React__namespace.createElement("circle", {
|
|
30810
30818
|
className: "movable-point-hitbox",
|
|
30811
30819
|
r: hitboxSizePx / 2,
|
|
@@ -30894,7 +30902,7 @@ const MovableLine = props => {
|
|
|
30894
30902
|
function useControlPoint(point, color, onMovePoint) {
|
|
30895
30903
|
const {
|
|
30896
30904
|
snapStep,
|
|
30897
|
-
|
|
30905
|
+
disableKeyboardInteraction
|
|
30898
30906
|
} = useGraphConfig();
|
|
30899
30907
|
const [focused, setFocused] = React.useState(false);
|
|
30900
30908
|
const keyboardHandleRef = React.useRef(null);
|
|
@@ -30902,7 +30910,7 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
30902
30910
|
gestureTarget: keyboardHandleRef,
|
|
30903
30911
|
point,
|
|
30904
30912
|
onMove: onMovePoint,
|
|
30905
|
-
|
|
30913
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30906
30914
|
});
|
|
30907
30915
|
const visiblePointRef = React.useRef(null);
|
|
30908
30916
|
const {
|
|
@@ -30911,12 +30919,12 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
30911
30919
|
gestureTarget: visiblePointRef,
|
|
30912
30920
|
point,
|
|
30913
30921
|
onMove: onMovePoint,
|
|
30914
|
-
|
|
30922
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30915
30923
|
});
|
|
30916
30924
|
const focusableHandle = /*#__PURE__*/React__namespace.createElement("g", {
|
|
30917
30925
|
"data-testid": "movable-point__focusable-handle",
|
|
30918
30926
|
className: "movable-point__focusable-handle",
|
|
30919
|
-
tabIndex:
|
|
30927
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
30920
30928
|
ref: keyboardHandleRef,
|
|
30921
30929
|
onFocus: () => setFocused(true),
|
|
30922
30930
|
onBlur: () => setFocused(false)
|
|
@@ -30950,7 +30958,7 @@ const Line$1 = props => {
|
|
|
30950
30958
|
range,
|
|
30951
30959
|
graphDimensionsInPixels,
|
|
30952
30960
|
snapStep,
|
|
30953
|
-
|
|
30961
|
+
disableKeyboardInteraction
|
|
30954
30962
|
} = useGraphConfig();
|
|
30955
30963
|
let startExtend = undefined;
|
|
30956
30964
|
let endExtend = undefined;
|
|
@@ -30968,11 +30976,11 @@ const Line$1 = props => {
|
|
|
30968
30976
|
onMove: newPoint => {
|
|
30969
30977
|
onMove(mafs.vec.sub(newPoint, start));
|
|
30970
30978
|
},
|
|
30971
|
-
|
|
30979
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30972
30980
|
});
|
|
30973
30981
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("g", {
|
|
30974
30982
|
ref: line,
|
|
30975
|
-
tabIndex:
|
|
30983
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
30976
30984
|
className: "movable-line",
|
|
30977
30985
|
"data-testid": "movable-line",
|
|
30978
30986
|
style: {
|
|
@@ -31443,7 +31451,7 @@ function calculateBisectorPoint(point1, point2, vertex, isReflex, allowReflex, a
|
|
|
31443
31451
|
return scaledBisector;
|
|
31444
31452
|
}
|
|
31445
31453
|
|
|
31446
|
-
const
|
|
31454
|
+
const MovablePoint$1 = props => {
|
|
31447
31455
|
const {
|
|
31448
31456
|
snapStep
|
|
31449
31457
|
} = useGraphConfig();
|
|
@@ -31453,16 +31461,15 @@ const StyledMovablePoint = props => {
|
|
|
31453
31461
|
onMove,
|
|
31454
31462
|
cursor,
|
|
31455
31463
|
color = wonderBlocksTokens.color.blue,
|
|
31456
|
-
|
|
31464
|
+
constrain = p => snap(snapStep, p)
|
|
31457
31465
|
} = props;
|
|
31458
|
-
const snapToValue = snapTo ?? "grid";
|
|
31459
31466
|
const {
|
|
31460
31467
|
dragging
|
|
31461
31468
|
} = useDraggable({
|
|
31462
31469
|
gestureTarget: elementRef,
|
|
31463
31470
|
point,
|
|
31464
31471
|
onMove,
|
|
31465
|
-
|
|
31472
|
+
constrainKeyboardMovement: constrain
|
|
31466
31473
|
});
|
|
31467
31474
|
return /*#__PURE__*/React__namespace.createElement(MovablePointView, {
|
|
31468
31475
|
ref: elementRef,
|
|
@@ -31478,8 +31485,10 @@ const StyledMovablePoint = props => {
|
|
|
31478
31485
|
};
|
|
31479
31486
|
|
|
31480
31487
|
const PolygonGraph = props => {
|
|
31481
|
-
const [focused, setFocused] = React__namespace.useState(false);
|
|
31482
31488
|
const [hovered, setHovered] = React__namespace.useState(false);
|
|
31489
|
+
// This is more so required for the re-rendering that occurs when state
|
|
31490
|
+
// updates; specifically with regard to line weighting and polygon focus.
|
|
31491
|
+
const [focusVisible, setFocusVisible] = React__namespace.useState(false);
|
|
31483
31492
|
const {
|
|
31484
31493
|
dispatch
|
|
31485
31494
|
} = props;
|
|
@@ -31489,10 +31498,10 @@ const PolygonGraph = props => {
|
|
|
31489
31498
|
showSides,
|
|
31490
31499
|
range,
|
|
31491
31500
|
snapStep,
|
|
31492
|
-
snapTo
|
|
31501
|
+
snapTo = "grid"
|
|
31493
31502
|
} = props.graphState;
|
|
31494
31503
|
const {
|
|
31495
|
-
|
|
31504
|
+
disableKeyboardInteraction
|
|
31496
31505
|
} = useGraphConfig();
|
|
31497
31506
|
|
|
31498
31507
|
// TODO(benchristel): can the default set of points be removed here? I don't
|
|
@@ -31500,7 +31509,7 @@ const PolygonGraph = props => {
|
|
|
31500
31509
|
const points = coords ?? [[0, 0]];
|
|
31501
31510
|
const ref = React__namespace.useRef(null);
|
|
31502
31511
|
const dragReferencePoint = points[0];
|
|
31503
|
-
const
|
|
31512
|
+
const constrain = ["angles", "sides"].includes(snapTo) ? p => p : p => snap(snapStep, p);
|
|
31504
31513
|
const {
|
|
31505
31514
|
dragging
|
|
31506
31515
|
} = useDraggable({
|
|
@@ -31510,16 +31519,15 @@ const PolygonGraph = props => {
|
|
|
31510
31519
|
const delta = mafs.vec.sub(newPoint, dragReferencePoint);
|
|
31511
31520
|
dispatch(actions.polygon.moveAll(delta));
|
|
31512
31521
|
},
|
|
31513
|
-
|
|
31522
|
+
constrainKeyboardMovement: constrain
|
|
31514
31523
|
});
|
|
31515
|
-
const active = hovered || focused || dragging;
|
|
31516
31524
|
const lastMoveTime = React__namespace.useRef(0);
|
|
31517
31525
|
const lines = getLines(points);
|
|
31518
31526
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Polygon, {
|
|
31519
31527
|
points: [...points],
|
|
31520
31528
|
color: "var(--movable-line-stroke-color)",
|
|
31521
31529
|
svgPolygonProps: {
|
|
31522
|
-
strokeWidth:
|
|
31530
|
+
strokeWidth: focusVisible ? "var(--movable-line-stroke-weight-active)" : "var(--movable-line-stroke-weight)",
|
|
31523
31531
|
style: {
|
|
31524
31532
|
fill: "transparent"
|
|
31525
31533
|
}
|
|
@@ -31534,11 +31542,10 @@ const PolygonGraph = props => {
|
|
|
31534
31542
|
key: "angle-" + i,
|
|
31535
31543
|
centerPoint: point,
|
|
31536
31544
|
endPoints: [pt1, pt2],
|
|
31537
|
-
active: active,
|
|
31538
31545
|
range: range,
|
|
31539
31546
|
polygonLines: lines,
|
|
31540
31547
|
showAngles: !!showAngles,
|
|
31541
|
-
snapTo:
|
|
31548
|
+
snapTo: snapTo
|
|
31542
31549
|
});
|
|
31543
31550
|
}), showSides && lines.map((_ref, i) => {
|
|
31544
31551
|
let [start, end] = _ref;
|
|
@@ -31554,21 +31561,29 @@ const PolygonGraph = props => {
|
|
|
31554
31561
|
color: "transparent",
|
|
31555
31562
|
svgPolygonProps: {
|
|
31556
31563
|
ref,
|
|
31557
|
-
tabIndex:
|
|
31564
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
31558
31565
|
strokeWidth: TARGET_SIZE,
|
|
31559
31566
|
style: {
|
|
31560
31567
|
cursor: dragging ? "grabbing" : "grab",
|
|
31561
31568
|
fill: hovered ? "var(--mafs-blue)" : "transparent"
|
|
31562
31569
|
},
|
|
31563
|
-
onFocus: () => setFocused(true),
|
|
31564
|
-
onBlur: () => setFocused(false),
|
|
31565
31570
|
onMouseEnter: () => setHovered(true),
|
|
31566
31571
|
onMouseLeave: () => setHovered(false),
|
|
31572
|
+
// Required to remove line weighting when user clicks away
|
|
31573
|
+
// from the focused polygon
|
|
31574
|
+
onKeyDownCapture: () => {
|
|
31575
|
+
setFocusVisible(hasFocusVisible(ref.current));
|
|
31576
|
+
},
|
|
31577
|
+
// Required for lines to darken on focus
|
|
31578
|
+
onFocus: () => setFocusVisible(hasFocusVisible(ref.current)),
|
|
31579
|
+
// Required for line weighting to update on blur. Without this,
|
|
31580
|
+
// the user has to hover over the shape for it to update
|
|
31581
|
+
onBlur: () => setFocusVisible(hasFocusVisible(ref.current)),
|
|
31567
31582
|
className: "movable-polygon"
|
|
31568
31583
|
}
|
|
31569
|
-
}), points.map((point, i) => /*#__PURE__*/React__namespace.createElement(
|
|
31584
|
+
}), points.map((point, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31570
31585
|
key: "point-" + i,
|
|
31571
|
-
|
|
31586
|
+
constrain: constrain,
|
|
31572
31587
|
point: point,
|
|
31573
31588
|
onMove: destination => {
|
|
31574
31589
|
const now = Date.now();
|
|
@@ -31587,6 +31602,17 @@ function getLines(points) {
|
|
|
31587
31602
|
return [point, next];
|
|
31588
31603
|
});
|
|
31589
31604
|
}
|
|
31605
|
+
const hasFocusVisible = element => {
|
|
31606
|
+
const matches = selector => element?.matches(selector) ?? false;
|
|
31607
|
+
try {
|
|
31608
|
+
return matches(":focus-visible");
|
|
31609
|
+
} catch (e) {
|
|
31610
|
+
// jsdom doesn't support :focus-visible
|
|
31611
|
+
// (see https://github.com/jsdom/jsdom/issues/3426),
|
|
31612
|
+
// so the call to matches(":focus-visible") will fail in tests.
|
|
31613
|
+
return matches(":focus");
|
|
31614
|
+
}
|
|
31615
|
+
};
|
|
31590
31616
|
|
|
31591
31617
|
function getGradableGraph(state, initialGraph) {
|
|
31592
31618
|
if (!state.hasBeenInteractedWith) {
|
|
@@ -31650,9 +31676,17 @@ function getGradableGraph(state, initialGraph) {
|
|
|
31650
31676
|
};
|
|
31651
31677
|
}
|
|
31652
31678
|
if (state.type === "angle" && initialGraph.type === "angle") {
|
|
31679
|
+
// We're going to reverse the coords for scoring if the angle is clockwise and
|
|
31680
|
+
// we don't allow reflex angles. This is because the angle is largely defined
|
|
31681
|
+
// by the order of the points in the coords array, and we want to maintain
|
|
31682
|
+
// the same angle scoring with the legacy graph (which had a bug).
|
|
31683
|
+
// (LEMS-2190): When we remove the legacy graph, move this logic to the scoring function.
|
|
31684
|
+
const areClockwise = clockwise$1([state.coords[0], state.coords[2], state.coords[1]]);
|
|
31685
|
+
const shouldReverseCoords = areClockwise && !state.allowReflexAngles;
|
|
31686
|
+
const coords = shouldReverseCoords ? state.coords.slice().reverse() : state.coords;
|
|
31653
31687
|
return {
|
|
31654
31688
|
...initialGraph,
|
|
31655
|
-
coords
|
|
31689
|
+
coords,
|
|
31656
31690
|
allowReflexAngles: state.allowReflexAngles
|
|
31657
31691
|
};
|
|
31658
31692
|
}
|
|
@@ -31684,7 +31718,7 @@ function CircleGraph(props) {
|
|
|
31684
31718
|
center: center,
|
|
31685
31719
|
radius: getRadius(graphState),
|
|
31686
31720
|
onMove: c => dispatch(actions.circle.moveCenter(c))
|
|
31687
|
-
}), /*#__PURE__*/React__namespace.createElement(
|
|
31721
|
+
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31688
31722
|
point: radiusPoint,
|
|
31689
31723
|
cursor: "ew-resize",
|
|
31690
31724
|
onMove: newRadiusPoint => {
|
|
@@ -31700,7 +31734,7 @@ function MovableCircle(props) {
|
|
|
31700
31734
|
} = props;
|
|
31701
31735
|
const {
|
|
31702
31736
|
snapStep,
|
|
31703
|
-
|
|
31737
|
+
disableKeyboardInteraction
|
|
31704
31738
|
} = useGraphConfig();
|
|
31705
31739
|
const draggableRef = React.useRef(null);
|
|
31706
31740
|
const {
|
|
@@ -31709,13 +31743,13 @@ function MovableCircle(props) {
|
|
|
31709
31743
|
gestureTarget: draggableRef,
|
|
31710
31744
|
point: center,
|
|
31711
31745
|
onMove,
|
|
31712
|
-
|
|
31746
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
31713
31747
|
});
|
|
31714
31748
|
const [centerPx] = useTransformVectorsToPixels(center);
|
|
31715
31749
|
const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
|
|
31716
31750
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
31717
31751
|
ref: draggableRef,
|
|
31718
|
-
tabIndex:
|
|
31752
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
31719
31753
|
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
|
|
31720
31754
|
}, /*#__PURE__*/React__namespace.createElement("ellipse", {
|
|
31721
31755
|
className: "focus-ring",
|
|
@@ -31796,7 +31830,7 @@ function QuadraticGraph(props) {
|
|
|
31796
31830
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Plot.OfX, {
|
|
31797
31831
|
y: y,
|
|
31798
31832
|
color: wonderBlocksTokens.color.blue
|
|
31799
|
-
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(
|
|
31833
|
+
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31800
31834
|
key: "point-" + i,
|
|
31801
31835
|
point: coord,
|
|
31802
31836
|
onMove: destination => dispatch(actions.quadratic.movePoint(i, destination))
|
|
@@ -31856,7 +31890,7 @@ function SinusoidGraph(props) {
|
|
|
31856
31890
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Plot.OfX, {
|
|
31857
31891
|
y: x => computeSine(x, coeffRef.current),
|
|
31858
31892
|
color: wonderBlocksTokens.color.blue
|
|
31859
|
-
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(
|
|
31893
|
+
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31860
31894
|
key: "point-" + i,
|
|
31861
31895
|
point: coord,
|
|
31862
31896
|
onMove: destination => dispatch(actions.sinusoid.movePoint(i, destination))
|
|
@@ -31912,7 +31946,6 @@ function AngleGraph(props) {
|
|
|
31912
31946
|
showAngles,
|
|
31913
31947
|
range,
|
|
31914
31948
|
allowReflexAngles,
|
|
31915
|
-
angleOffsetDeg,
|
|
31916
31949
|
snapDegrees
|
|
31917
31950
|
} = graphState;
|
|
31918
31951
|
|
|
@@ -31951,8 +31984,6 @@ function AngleGraph(props) {
|
|
|
31951
31984
|
coords: endPoints,
|
|
31952
31985
|
allowReflexAngles: allowReflexAngles || false,
|
|
31953
31986
|
// Whether to allow reflex angles or not
|
|
31954
|
-
angleOffsetDeg: angleOffsetDeg || 0,
|
|
31955
|
-
// The angle offset from the x-axis
|
|
31956
31987
|
snapDegrees: snapDegrees || 1,
|
|
31957
31988
|
// The multiple of degrees to snap to
|
|
31958
31989
|
range: range,
|
|
@@ -31960,19 +31991,65 @@ function AngleGraph(props) {
|
|
|
31960
31991
|
};
|
|
31961
31992
|
|
|
31962
31993
|
// Render the lines, angle, and then movable points
|
|
31963
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, svgLines, /*#__PURE__*/React__namespace.createElement(Angle, angleParams),
|
|
31964
|
-
|
|
31965
|
-
|
|
31966
|
-
|
|
31967
|
-
|
|
31968
|
-
|
|
31994
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, svgLines, /*#__PURE__*/React__namespace.createElement(Angle, angleParams), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31995
|
+
point: coords[1],
|
|
31996
|
+
constrain: p => p,
|
|
31997
|
+
onMove: destination => dispatch(actions.angle.movePoint(1, destination))
|
|
31998
|
+
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31999
|
+
point: coords[0],
|
|
32000
|
+
constrain: getAngleSideConstraint(coords[0], coords[1], snapDegrees || 1),
|
|
32001
|
+
onMove: destination => dispatch(actions.angle.movePoint(0, destination))
|
|
32002
|
+
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
32003
|
+
point: coords[2],
|
|
32004
|
+
constrain: getAngleSideConstraint(coords[2], coords[1], snapDegrees || 1),
|
|
32005
|
+
onMove: destination => dispatch(actions.angle.movePoint(2, destination))
|
|
32006
|
+
}));
|
|
32007
|
+
}
|
|
32008
|
+
const positiveX = [1, 0];
|
|
32009
|
+
const negativeX = [-1, 0];
|
|
32010
|
+
const positiveY = [0, 1];
|
|
32011
|
+
const negativeY = [0, -1];
|
|
32012
|
+
function getAngleSideConstraint(sidePoint, vertex, snapDegrees) {
|
|
32013
|
+
const currentAngle = calculateAngleInDegrees(mafs.vec.sub(sidePoint, vertex));
|
|
32014
|
+
|
|
32015
|
+
// Find the rays that start at the current point and point up, down, left
|
|
32016
|
+
// and right.
|
|
32017
|
+
const leftRay = [sidePoint, mafs.vec.add(sidePoint, negativeX)];
|
|
32018
|
+
const rightRay = [sidePoint, mafs.vec.add(sidePoint, positiveX)];
|
|
32019
|
+
const upRay = [sidePoint, mafs.vec.add(sidePoint, positiveY)];
|
|
32020
|
+
const downRay = [sidePoint, mafs.vec.add(sidePoint, negativeY)];
|
|
32021
|
+
|
|
32022
|
+
// find the angles that lie one snap step clockwise and counter-clockwise
|
|
32023
|
+
// from the current angle. These are the angles to which the side can be
|
|
32024
|
+
// moved.
|
|
32025
|
+
const oneStepCounterClockwise = currentAngle + snapDegrees;
|
|
32026
|
+
const oneStepClockwise = currentAngle - snapDegrees;
|
|
32027
|
+
|
|
32028
|
+
// find the rays that start from the vertex and point in the direction of
|
|
32029
|
+
// the angles we just computed.
|
|
32030
|
+
const counterClockwiseRay = [vertex, mafs.vec.add(vertex, polar(1, oneStepCounterClockwise))];
|
|
32031
|
+
const clockwiseRay = [vertex, mafs.vec.add(vertex, polar(1, oneStepClockwise))];
|
|
32032
|
+
|
|
32033
|
+
// find the intersections of those rays with the horizontal and vertical
|
|
32034
|
+
// rays extending from the sidePoint. These intersections are the points to
|
|
32035
|
+
// which sidePoint can move that will result in a rotation of `snapDegrees`.
|
|
32036
|
+
const left = findIntersectionOfRays(leftRay, counterClockwiseRay) ?? findIntersectionOfRays(leftRay, clockwiseRay);
|
|
32037
|
+
const right = findIntersectionOfRays(rightRay, counterClockwiseRay) ?? findIntersectionOfRays(rightRay, clockwiseRay);
|
|
32038
|
+
const up = findIntersectionOfRays(upRay, counterClockwiseRay) ?? findIntersectionOfRays(upRay, clockwiseRay);
|
|
32039
|
+
const down = findIntersectionOfRays(downRay, counterClockwiseRay) ?? findIntersectionOfRays(downRay, clockwiseRay);
|
|
32040
|
+
return {
|
|
32041
|
+
up: up ?? sidePoint,
|
|
32042
|
+
down: down ?? sidePoint,
|
|
32043
|
+
left: left ?? sidePoint,
|
|
32044
|
+
right: right ?? sidePoint
|
|
32045
|
+
};
|
|
31969
32046
|
}
|
|
31970
32047
|
|
|
31971
32048
|
function PointGraph(props) {
|
|
31972
32049
|
const {
|
|
31973
32050
|
dispatch
|
|
31974
32051
|
} = props;
|
|
31975
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, props.graphState.coords.map((point, i) => /*#__PURE__*/React__namespace.createElement(
|
|
32052
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, props.graphState.coords.map((point, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31976
32053
|
key: i,
|
|
31977
32054
|
point: point,
|
|
31978
32055
|
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination))
|
|
@@ -32004,7 +32081,7 @@ function Protractor() {
|
|
|
32004
32081
|
gestureTarget: draggableRef,
|
|
32005
32082
|
onMove: setCenter,
|
|
32006
32083
|
point: center,
|
|
32007
|
-
|
|
32084
|
+
constrainKeyboardMovement: point => bound$1({
|
|
32008
32085
|
snapStep,
|
|
32009
32086
|
range,
|
|
32010
32087
|
point
|
|
@@ -32120,7 +32197,8 @@ const MafsGraph = props => {
|
|
|
32120
32197
|
state,
|
|
32121
32198
|
dispatch,
|
|
32122
32199
|
labels,
|
|
32123
|
-
hintMode
|
|
32200
|
+
hintMode,
|
|
32201
|
+
readOnly
|
|
32124
32202
|
} = props;
|
|
32125
32203
|
const [width, height] = props.box;
|
|
32126
32204
|
const tickStep = props.step;
|
|
@@ -32136,7 +32214,7 @@ const MafsGraph = props => {
|
|
|
32136
32214
|
width,
|
|
32137
32215
|
height,
|
|
32138
32216
|
labels,
|
|
32139
|
-
hintMode
|
|
32217
|
+
disableKeyboardInteraction: hintMode || readOnly
|
|
32140
32218
|
}
|
|
32141
32219
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
32142
32220
|
className: "mafs-graph",
|
|
@@ -32501,6 +32579,9 @@ const getAngleCoords = params => {
|
|
|
32501
32579
|
if (graph.coords) {
|
|
32502
32580
|
return graph.coords;
|
|
32503
32581
|
}
|
|
32582
|
+
if (graph.startCoords) {
|
|
32583
|
+
return graph.startCoords;
|
|
32584
|
+
}
|
|
32504
32585
|
const {
|
|
32505
32586
|
snapDegrees,
|
|
32506
32587
|
angleOffsetDeg
|
|
@@ -32530,6 +32611,7 @@ const getAngleCoords = params => {
|
|
|
32530
32611
|
return coords;
|
|
32531
32612
|
};
|
|
32532
32613
|
|
|
32614
|
+
const minDistanceBetweenAngleVertexAndSidePoint = 2;
|
|
32533
32615
|
function interactiveGraphReducer(state, action) {
|
|
32534
32616
|
switch (action.type) {
|
|
32535
32617
|
case REINITIALIZE:
|
|
@@ -32700,23 +32782,30 @@ function doMovePoint(state, action) {
|
|
|
32700
32782
|
case "angle":
|
|
32701
32783
|
// If the index is 1, we are moving the vertex of the angle,
|
|
32702
32784
|
// which will move the other two points as well
|
|
32703
|
-
|
|
32704
|
-
|
|
32785
|
+
const newState = (() => {
|
|
32786
|
+
if (action.index === 1) {
|
|
32787
|
+
const updatedCoords = boundAndSnapAngleVertex(state, action);
|
|
32788
|
+
return {
|
|
32789
|
+
...state,
|
|
32790
|
+
hasBeenInteractedWith: true,
|
|
32791
|
+
coords: updatedCoords
|
|
32792
|
+
};
|
|
32793
|
+
}
|
|
32705
32794
|
return {
|
|
32706
32795
|
...state,
|
|
32707
32796
|
hasBeenInteractedWith: true,
|
|
32708
|
-
coords:
|
|
32797
|
+
coords: setAtIndex({
|
|
32798
|
+
array: state.coords,
|
|
32799
|
+
index: action.index,
|
|
32800
|
+
newValue: boundAndSnapAngleEndPoints(action.destination, state, action.index)
|
|
32801
|
+
})
|
|
32709
32802
|
};
|
|
32803
|
+
})();
|
|
32804
|
+
if (angleSidePointsTooCloseToVertex(newState)) {
|
|
32805
|
+
// cancel the move
|
|
32806
|
+
return state;
|
|
32710
32807
|
}
|
|
32711
|
-
return
|
|
32712
|
-
...state,
|
|
32713
|
-
hasBeenInteractedWith: true,
|
|
32714
|
-
coords: setAtIndex({
|
|
32715
|
-
array: state.coords,
|
|
32716
|
-
index: action.index,
|
|
32717
|
-
newValue: boundAndSnapAngleEndPoints(action.destination, state, action.index)
|
|
32718
|
-
})
|
|
32719
|
-
};
|
|
32808
|
+
return newState;
|
|
32720
32809
|
case "polygon":
|
|
32721
32810
|
let newValue;
|
|
32722
32811
|
if (state.snapTo === "sides") {
|
|
@@ -32809,11 +32898,7 @@ function doMoveCenter(state, action) {
|
|
|
32809
32898
|
case "circle":
|
|
32810
32899
|
{
|
|
32811
32900
|
// Constrain the center of the circle to the chart range
|
|
32812
|
-
const constrainedCenter =
|
|
32813
|
-
snapStep: state.snapStep,
|
|
32814
|
-
range: state.range,
|
|
32815
|
-
point: action.destination
|
|
32816
|
-
});
|
|
32901
|
+
const constrainedCenter = boundAndSnapToGrid(action.destination, state);
|
|
32817
32902
|
|
|
32818
32903
|
// Reposition the radius point based on the new center
|
|
32819
32904
|
// (spread to make sure we're not going to mutate anything)
|
|
@@ -32848,10 +32933,10 @@ function doMoveRadiusPoint(state, action) {
|
|
|
32848
32933
|
case "circle":
|
|
32849
32934
|
{
|
|
32850
32935
|
const [xMin, xMax] = state.range[X];
|
|
32851
|
-
const nextRadiusPoint = [
|
|
32936
|
+
const nextRadiusPoint = snap(state.snapStep, [
|
|
32852
32937
|
// Constrain to graph range
|
|
32853
32938
|
// The +0 is to convert -0 to +0
|
|
32854
|
-
clamp(action.destination[X] + 0, xMin, xMax), state.center[1]];
|
|
32939
|
+
clamp(action.destination[X] + 0, xMin, xMax), state.center[1]]);
|
|
32855
32940
|
if (___default["default"].isEqual(nextRadiusPoint, state.center)) {
|
|
32856
32941
|
return state;
|
|
32857
32942
|
}
|
|
@@ -32941,17 +33026,16 @@ function boundAndSnapAngleVertex(_ref2, _ref3) {
|
|
|
32941
33026
|
|
|
32942
33027
|
// Get the current and upcoming positions of the vertex
|
|
32943
33028
|
const startingVertex = coordsCopy[1];
|
|
32944
|
-
|
|
32945
|
-
|
|
32946
|
-
|
|
32947
|
-
|
|
32948
|
-
|
|
33029
|
+
|
|
33030
|
+
// Prevent the vertex from getting too close to the edge, so that all
|
|
33031
|
+
// points of the angle can fit within the graph bounds.
|
|
33032
|
+
const insetAmount = mafs.vec.add(snapStep, [minDistanceBetweenAngleVertexAndSidePoint, minDistanceBetweenAngleVertexAndSidePoint]);
|
|
33033
|
+
const newVertex = clampToBox(inset(insetAmount, range), snap(snapStep, destination));
|
|
32949
33034
|
|
|
32950
33035
|
// Get the vector from the starting vertex to the new vertex
|
|
32951
33036
|
const delta = mafs.vec.add(newVertex, reverseVector(startingVertex));
|
|
32952
33037
|
|
|
32953
33038
|
// Apply the delta to each of the other two points so that the angle is maintained
|
|
32954
|
-
let valid = true;
|
|
32955
33039
|
const newPoints = {};
|
|
32956
33040
|
for (const i of [0, 2]) {
|
|
32957
33041
|
const oldPoint = coordsCopy[i];
|
|
@@ -32960,22 +33044,14 @@ function boundAndSnapAngleVertex(_ref2, _ref3) {
|
|
|
32960
33044
|
angle *= Math.PI / 180;
|
|
32961
33045
|
newPoint = constrainToBoundsOnAngle(newPoint, angle, range, snapStep);
|
|
32962
33046
|
newPoints[i] = newPoint;
|
|
32963
|
-
|
|
32964
|
-
// Check if the new point is too close to the vertex
|
|
32965
|
-
if (tooClose(newVertex, newPoint)) {
|
|
32966
|
-
valid = false;
|
|
32967
|
-
}
|
|
32968
33047
|
}
|
|
32969
33048
|
|
|
32970
33049
|
// Update the vertex after snapping to the snapStep
|
|
32971
33050
|
newPoints[1] = newVertex;
|
|
32972
|
-
|
|
32973
|
-
|
|
32974
|
-
|
|
32975
|
-
|
|
32976
|
-
coordsCopy[i] = newPoint;
|
|
32977
|
-
});
|
|
32978
|
-
}
|
|
33051
|
+
Object.entries(newPoints).forEach(_ref4 => {
|
|
33052
|
+
let [i, newPoint] = _ref4;
|
|
33053
|
+
coordsCopy[i] = newPoint;
|
|
33054
|
+
});
|
|
32979
33055
|
return coordsCopy;
|
|
32980
33056
|
}
|
|
32981
33057
|
|
|
@@ -33041,10 +33117,17 @@ function boundAndSnapAngleEndPoints(destinationPoint, _ref5, index) {
|
|
|
33041
33117
|
|
|
33042
33118
|
// Snap the angle to the nearest multiple of snapDegrees (if provided)
|
|
33043
33119
|
angle = Math.round((angle - offsetDegrees) / snap) * snap + offsetDegrees;
|
|
33044
|
-
|
|
33120
|
+
|
|
33121
|
+
// add 0.01 to prevent rounding errors from causing the point to snap to
|
|
33122
|
+
// a location that is too close to the vertex.
|
|
33123
|
+
const minDistance = minDistanceBetweenAngleVertexAndSidePoint + 0.01;
|
|
33124
|
+
const distance = Math.max(mafs.vec.dist(coordsCopy[index], vertex), minDistance);
|
|
33045
33125
|
const snappedValue = mafs.vec.add(vertex, polar(distance, angle));
|
|
33046
33126
|
return snappedValue;
|
|
33047
33127
|
}
|
|
33128
|
+
function angleSidePointsTooCloseToVertex(state) {
|
|
33129
|
+
return tooClose(state.coords[0], state.coords[1], state.range) || tooClose(state.coords[2], state.coords[1], state.range);
|
|
33130
|
+
}
|
|
33048
33131
|
function boundAndSnapToPolygonAngle(destinationPoint, _ref6, index) {
|
|
33049
33132
|
let {
|
|
33050
33133
|
range,
|
|
@@ -33275,7 +33358,12 @@ const StatefulMafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref)
|
|
|
33275
33358
|
React.useEffect(() => {
|
|
33276
33359
|
dispatch(changeRange([[xMinRange, xMaxRange], [yMinRange, yMaxRange]]));
|
|
33277
33360
|
}, [dispatch, xMinRange, xMaxRange, yMinRange, yMaxRange]);
|
|
33361
|
+
|
|
33362
|
+
// Update the graph whenever any of the following values changes.
|
|
33363
|
+
// This is necessary to keep the graph previews in sync with the updated
|
|
33364
|
+
// graph settings within the interative graph editor.
|
|
33278
33365
|
const numSegments = graph.type === "segment" ? graph.numSegments : null;
|
|
33366
|
+
const numPoints = graph.type === "point" ? graph.numPoints : null;
|
|
33279
33367
|
const numSides = graph.type === "polygon" ? graph.numSides : null;
|
|
33280
33368
|
const snapTo = graph.type === "polygon" ? graph.snapTo : null;
|
|
33281
33369
|
const showAngles = graph.type === "polygon" ? graph.showAngles : null;
|
|
@@ -33290,7 +33378,7 @@ const StatefulMafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref)
|
|
|
33290
33378
|
if (latestPropsRef.current !== originalPropsRef.current) {
|
|
33291
33379
|
dispatch(reinitialize(latestPropsRef.current));
|
|
33292
33380
|
}
|
|
33293
|
-
}, [graph.type, numSegments, numSides, snapTo, showAngles, showSides, latestPropsRef, graph.startCoords]);
|
|
33381
|
+
}, [graph.type, numPoints, numSegments, numSides, snapTo, showAngles, showSides, latestPropsRef, graph.startCoords]);
|
|
33294
33382
|
return /*#__PURE__*/React__namespace.createElement(MafsGraph, _extends({}, props, {
|
|
33295
33383
|
state: state,
|
|
33296
33384
|
dispatch: dispatch
|
|
@@ -33353,6 +33441,10 @@ const makeInvalidTypeError = (functionName, graphType) => {
|
|
|
33353
33441
|
|
|
33354
33442
|
// There's no transform function in exports
|
|
33355
33443
|
|
|
33444
|
+
// (LEMS-2190): Move the Mafs Angle Graph coordinate reversal logic in interactive-graph-state.ts
|
|
33445
|
+
// to this file when we remove the legacy graph. This logic allows us to support bi-directional angles
|
|
33446
|
+
// for the new (non-reflexive) Mafs graphs, while maintaining the same scoring behaviour as the legacy graph.
|
|
33447
|
+
// Once the legacy graph is removed, we should move this logic directly into the validate function below.
|
|
33356
33448
|
class LegacyInteractiveGraph extends React__namespace.Component {
|
|
33357
33449
|
static contextType = PerseusI18nContext;
|
|
33358
33450
|
angle;
|
|
@@ -34590,7 +34682,8 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
34590
34682
|
snapStep: snapStep,
|
|
34591
34683
|
box: box,
|
|
34592
34684
|
showTooltips: !!this.props.showTooltips,
|
|
34593
|
-
hintMode: this.props.hintMode
|
|
34685
|
+
hintMode: this.props.hintMode,
|
|
34686
|
+
readOnly: this.props.apiOptions?.readOnly
|
|
34594
34687
|
}));
|
|
34595
34688
|
}
|
|
34596
34689
|
return /*#__PURE__*/React__namespace.createElement(LegacyInteractiveGraph, _extends({
|
|
@@ -44512,7 +44605,7 @@ const init = function (options) {
|
|
|
44512
44605
|
|
|
44513
44606
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44514
44607
|
const libName = "@khanacademy/perseus";
|
|
44515
|
-
const libVersion = "
|
|
44608
|
+
const libVersion = "28.0.0";
|
|
44516
44609
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44517
44610
|
|
|
44518
44611
|
const apiVersion = {
|
|
@@ -45070,7 +45163,6 @@ const context = /*#__PURE__*/React__namespace.createContext(defaultContext);
|
|
|
45070
45163
|
const {
|
|
45071
45164
|
mapObject
|
|
45072
45165
|
} = objective_;
|
|
45073
|
-
/* eslint-disable-next-line react/no-unsafe */
|
|
45074
45166
|
class ServerItemRenderer extends React__namespace.Component {
|
|
45075
45167
|
static contextType = PerseusI18nContext;
|
|
45076
45168
|
// @ts-expect-error - TS2564 - Property 'questionRenderer' has no initializer and is not definitely assigned in the constructor.
|
|
@@ -46449,7 +46541,16 @@ class MultiRenderer extends React__namespace.Component {
|
|
|
46449
46541
|
// _annotateRendererArray() needs this
|
|
46450
46542
|
ref: null,
|
|
46451
46543
|
makeRenderer: () => /*#__PURE__*/React__namespace.createElement(HintsRenderer, _extends({}, this._getRendererProps(), {
|
|
46452
|
-
findExternalWidgets: findExternalWidgets
|
|
46544
|
+
findExternalWidgets: findExternalWidgets
|
|
46545
|
+
// Note(Jeremy): The MultiRenderer codebase types are
|
|
46546
|
+
// slightly different from the rest of the codebase.
|
|
46547
|
+
// Ideally `HintNode` would spread the `Hint` type into it,
|
|
46548
|
+
// but there is a difference in optionality of `widgets`
|
|
46549
|
+
// and `images` and that causes a huge cascade of type
|
|
46550
|
+
// errors (they are truly optional, but most of our code
|
|
46551
|
+
// assumes they're provided/set). Ignoring this for now.
|
|
46552
|
+
// @ts-expect-error - TS2769 - Type 'HintNode' is not assignable to type 'Hint'.
|
|
46553
|
+
,
|
|
46453
46554
|
hints: [hint]
|
|
46454
46555
|
}))
|
|
46455
46556
|
};
|
|
@@ -48166,13 +48267,18 @@ exports.generateTestNumericInputWidget = generateTestNumericInputWidget;
|
|
|
48166
48267
|
exports.generateTestPerseusItem = generateTestPerseusItem;
|
|
48167
48268
|
exports.generateTestRadioWidget = generateTestRadioWidget;
|
|
48168
48269
|
exports.genericPerseusItemData = genericPerseusItemData;
|
|
48270
|
+
exports.getAngleCoords = getAngleCoords;
|
|
48169
48271
|
exports.getAnswerFromUserInput = getAnswerFromUserInput;
|
|
48170
48272
|
exports.getAnswersFromWidgets = getAnswersFromWidgets;
|
|
48171
48273
|
exports.getCircleCoords = getCircleCoords;
|
|
48172
48274
|
exports.getCorrectAnswerForWidgetId = getCorrectAnswerForWidgetId;
|
|
48173
48275
|
exports.getLineCoords = getLineCoords;
|
|
48174
48276
|
exports.getLinearSystemCoords = getLinearSystemCoords;
|
|
48277
|
+
exports.getPointCoords = getPointCoords;
|
|
48278
|
+
exports.getPolygonCoords = getPolygonCoords;
|
|
48279
|
+
exports.getQuadraticCoords = getQuadraticCoords;
|
|
48175
48280
|
exports.getSegmentCoords = getSegmentCoords;
|
|
48281
|
+
exports.getSinusoidCoords = getSinusoidCoords;
|
|
48176
48282
|
exports.getValidWidgetIds = getValidWidgetIds;
|
|
48177
48283
|
exports.getWidgetFromWidgetMap = getWidgetFromWidgetMap;
|
|
48178
48284
|
exports.getWidgetIdsFromContent = getWidgetIdsFromContent;
|