@khanacademy/perseus 27.2.0 → 28.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/image-loader.d.ts +2 -2
- package/dist/components/{info-tip.d.ts → info-tip/index.d.ts} +2 -2
- package/dist/components/info-tip/info-tip-base.d.ts +6 -0
- package/dist/components.d.ts +0 -1
- package/dist/es/index.js +452 -362
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +6 -2
- package/dist/es/strings.js.map +1 -1
- package/dist/hints-renderer.d.ts +2 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +438 -348
- package/dist/index.js.map +1 -1
- package/dist/interactive2/movable-point.d.ts +3 -3
- package/dist/perseus-api.d.ts +3 -0
- package/dist/perseus-types.d.ts +10 -6
- package/dist/renderer.d.ts +2 -1
- package/dist/server-item-renderer.d.ts +3 -0
- package/dist/strings.d.ts +2 -0
- package/dist/strings.js +6 -2
- package/dist/strings.js.map +1 -1
- package/dist/types.d.ts +7 -7
- package/dist/util/{katex-preprocess.d.ts → tex-preprocess.d.ts} +1 -1
- package/dist/widgets/expression.d.ts +20 -2
- package/dist/widgets/interactive-graphs/graphs/angle.d.ts +7 -0
- package/dist/widgets/interactive-graphs/graphs/components/angle-indicators.d.ts +0 -2
- package/dist/widgets/interactive-graphs/graphs/components/movable-point.d.ts +3 -2
- package/dist/widgets/interactive-graphs/graphs/polygon.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/use-draggable.d.ts +7 -1
- package/dist/widgets/interactive-graphs/locked-figures/locked-function.d.ts +1 -1
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +1 -0
- package/dist/widgets/interactive-graphs/math/geometry.d.ts +2 -1
- package/dist/widgets/interactive-graphs/reducer/initialize-graph-state.d.ts +8 -1
- package/dist/widgets/interactive-graphs/reducer/use-graph-config.d.ts +1 -1
- package/dist/widgets/interactive-graphs/stateful-mafs-graph.d.ts +1 -0
- package/dist/widgets/label-image.d.ts +6 -0
- package/package.json +8 -7
- package/dist/components/info-tip/info-tip.d.ts +0 -6
- package/dist/components/prop-check-box.d.ts +0 -4
package/dist/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",
|
|
@@ -743,9 +772,11 @@ const styles$E = aphrodite.StyleSheet.create({
|
|
|
743
772
|
borderRadius: 1
|
|
744
773
|
},
|
|
745
774
|
iconInactive: {
|
|
775
|
+
border: "2px solid transparent",
|
|
746
776
|
backgroundColor: wonderBlocksTokens.color.offBlack8
|
|
747
777
|
},
|
|
748
778
|
iconActive: {
|
|
779
|
+
border: `2px solid ${wonderBlocksTokens.color.white}`,
|
|
749
780
|
backgroundColor: wonderBlocksTokens.color.offBlack64
|
|
750
781
|
},
|
|
751
782
|
outerWrapper: {
|
|
@@ -1263,26 +1294,6 @@ const ClassNames = {
|
|
|
1263
1294
|
MOBILE: "perseus-mobile"
|
|
1264
1295
|
};
|
|
1265
1296
|
|
|
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
1297
|
const KhanMath = {
|
|
1287
1298
|
// Simplify formulas before display
|
|
1288
1299
|
cleanMath: function (expr) {
|
|
@@ -2587,7 +2598,7 @@ class Expression extends React__namespace.Component {
|
|
|
2587
2598
|
render() {
|
|
2588
2599
|
if (this.props.apiOptions.customKeypad) {
|
|
2589
2600
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
2590
|
-
className: aphrodite.css(styles$
|
|
2601
|
+
className: aphrodite.css(styles$C.mobileLabelInputWrapper)
|
|
2591
2602
|
}, !!this.props.visibleLabel && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
|
|
2592
2603
|
htmlFor: this._textareaId,
|
|
2593
2604
|
tag: "label"
|
|
@@ -2621,7 +2632,7 @@ class Expression extends React__namespace.Component {
|
|
|
2621
2632
|
ERROR_TITLE
|
|
2622
2633
|
} = this.context.strings;
|
|
2623
2634
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
2624
|
-
className: aphrodite.css(styles$
|
|
2635
|
+
className: aphrodite.css(styles$C.desktopLabelInputWrapper)
|
|
2625
2636
|
}, !!this.props.visibleLabel && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
|
|
2626
2637
|
htmlFor: this._textareaId,
|
|
2627
2638
|
tag: "label"
|
|
@@ -2662,7 +2673,7 @@ class Expression extends React__namespace.Component {
|
|
|
2662
2673
|
}))));
|
|
2663
2674
|
}
|
|
2664
2675
|
}
|
|
2665
|
-
const styles$
|
|
2676
|
+
const styles$C = aphrodite.StyleSheet.create({
|
|
2666
2677
|
mobileLabelInputWrapper: {
|
|
2667
2678
|
padding: "15px 4px 0"
|
|
2668
2679
|
},
|
|
@@ -9039,8 +9050,8 @@ function findChildOrAdd(elem, className) {
|
|
|
9039
9050
|
return $child;
|
|
9040
9051
|
}
|
|
9041
9052
|
var Tex$1 = {
|
|
9042
|
-
// Process a node and add math inside of it. This
|
|
9043
|
-
// format the math
|
|
9053
|
+
// Process a node and add math inside of it. This uses MathJax to
|
|
9054
|
+
// format the math.
|
|
9044
9055
|
//
|
|
9045
9056
|
// elem: The element which the math should be added to.
|
|
9046
9057
|
//
|
|
@@ -15435,7 +15446,7 @@ const DEFAULT_STATE$1 = {
|
|
|
15435
15446
|
// TODO(benchristel): this is a memory leak. We add items to
|
|
15436
15447
|
// tooltipResetFunctions, but never remove them.
|
|
15437
15448
|
const tooltipResetFunctions = [];
|
|
15438
|
-
class MovablePoint$
|
|
15449
|
+
class MovablePoint$5 {
|
|
15439
15450
|
graphie;
|
|
15440
15451
|
movable;
|
|
15441
15452
|
state;
|
|
@@ -15743,9 +15754,9 @@ class MovablePoint$4 {
|
|
|
15743
15754
|
* Displays a tooltip above the point, replacing any previous contents. If
|
|
15744
15755
|
* there is no tooltip initialized, adds the tooltip.
|
|
15745
15756
|
*
|
|
15746
|
-
* If the type of contents is string, the contents will be rendered
|
|
15747
|
-
*
|
|
15748
|
-
*
|
|
15757
|
+
* If the type of contents is string, the contents will be rendered as TeX
|
|
15758
|
+
* Otherwise, the content will be assumed to be a DOM node and will be
|
|
15759
|
+
* appended inside the tooltip.
|
|
15749
15760
|
*/
|
|
15750
15761
|
_showTooltip(contents) {
|
|
15751
15762
|
if (!this._tooltip) {
|
|
@@ -16568,10 +16579,10 @@ ___default["default"].extend(MovablePolygon.prototype, {
|
|
|
16568
16579
|
});
|
|
16569
16580
|
|
|
16570
16581
|
const Interactive2 = {
|
|
16571
|
-
MovablePoint: MovablePoint$
|
|
16582
|
+
MovablePoint: MovablePoint$5,
|
|
16572
16583
|
addMovablePoint: function (graphie, options) {
|
|
16573
16584
|
const movable = new Movable(graphie, {});
|
|
16574
|
-
return new MovablePoint$
|
|
16585
|
+
return new MovablePoint$5(graphie, movable, options);
|
|
16575
16586
|
},
|
|
16576
16587
|
MovableLine: MovableLine$4,
|
|
16577
16588
|
addMovableLine: function (graphie, options) {
|
|
@@ -16613,7 +16624,7 @@ const Interactive2 = {
|
|
|
16613
16624
|
}
|
|
16614
16625
|
};
|
|
16615
16626
|
|
|
16616
|
-
const MovablePoint$
|
|
16627
|
+
const MovablePoint$4 = GraphieClasses.createClass({
|
|
16617
16628
|
displayName: "MovablePoint",
|
|
16618
16629
|
movableProps: ["children"],
|
|
16619
16630
|
_getProps: function () {
|
|
@@ -16671,7 +16682,7 @@ const MovablePoint$3 = GraphieClasses.createClass({
|
|
|
16671
16682
|
});
|
|
16672
16683
|
|
|
16673
16684
|
// Include helper methods, such as MovablePoint.constrain.snap()
|
|
16674
|
-
___default["default"].extend(MovablePoint$
|
|
16685
|
+
___default["default"].extend(MovablePoint$4, Interactive2.MovablePoint);
|
|
16675
16686
|
const MovableLine$3 = GraphieClasses.createClass({
|
|
16676
16687
|
displayName: "MovableLine",
|
|
16677
16688
|
movableProps: ["children"],
|
|
@@ -16841,7 +16852,7 @@ var Movables = {
|
|
|
16841
16852
|
Label: Label$1,
|
|
16842
16853
|
Line: Line$3,
|
|
16843
16854
|
MovableLine: MovableLine$3,
|
|
16844
|
-
MovablePoint: MovablePoint$
|
|
16855
|
+
MovablePoint: MovablePoint$4,
|
|
16845
16856
|
Parabola: Parabola,
|
|
16846
16857
|
Path: Path,
|
|
16847
16858
|
Plot: Plot$2,
|
|
@@ -17199,17 +17210,15 @@ class ImageLoader extends React__namespace.Component {
|
|
|
17199
17210
|
src,
|
|
17200
17211
|
imgProps
|
|
17201
17212
|
} = this.props;
|
|
17202
|
-
let onKeyUp
|
|
17203
|
-
let onKeyDown
|
|
17213
|
+
let onKeyUp;
|
|
17214
|
+
let onKeyDown;
|
|
17204
17215
|
if (imgProps.onClick != null) {
|
|
17205
|
-
// @ts-expect-error - TS2322 - Type '(e: React.KeyboardEvent) => void' is not assignable to type 'null'.
|
|
17206
17216
|
onKeyUp = e => {
|
|
17207
17217
|
// 13 is enter key, 32 is space key
|
|
17208
17218
|
if (e.keyCode === 13 || e.keyCode === 32) {
|
|
17209
17219
|
imgProps.onClick && imgProps.onClick(e);
|
|
17210
17220
|
}
|
|
17211
17221
|
};
|
|
17212
|
-
// @ts-expect-error - TS2322 - Type '(e: React.KeyboardEvent) => void' is not assignable to type 'null'.
|
|
17213
17222
|
onKeyDown = e => {
|
|
17214
17223
|
// 32 is space key
|
|
17215
17224
|
if (e.keyCode === 32) {
|
|
@@ -17220,12 +17229,8 @@ class ImageLoader extends React__namespace.Component {
|
|
|
17220
17229
|
}
|
|
17221
17230
|
const staticUrl = getDependencies().staticUrl;
|
|
17222
17231
|
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
|
-
,
|
|
17232
|
+
src: staticUrl(src),
|
|
17233
|
+
onKeyUp: onKeyUp,
|
|
17229
17234
|
onKeyDown: onKeyDown
|
|
17230
17235
|
}, imgProps));
|
|
17231
17236
|
};
|
|
@@ -17716,18 +17721,14 @@ class SvgImage extends React__namespace.Component {
|
|
|
17716
17721
|
allowFullBleed: this.props.allowFullBleed && isImageProbablyPhotograph(imageSrc)
|
|
17717
17722
|
}, /*#__PURE__*/React__namespace.createElement(ImageLoader, {
|
|
17718
17723
|
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
|
-
,
|
|
17724
|
+
imgProps: imageProps,
|
|
17722
17725
|
preloader: preloader,
|
|
17723
17726
|
onUpdate: this.handleUpdate
|
|
17724
17727
|
}), extraGraphie);
|
|
17725
17728
|
}
|
|
17726
17729
|
imageProps.style = dimensions;
|
|
17727
17730
|
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
|
-
,
|
|
17731
|
+
src: imageSrc,
|
|
17731
17732
|
preloader: preloader,
|
|
17732
17733
|
imgProps: imageProps,
|
|
17733
17734
|
onUpdate: this.handleUpdate
|
|
@@ -17777,9 +17778,7 @@ class SvgImage extends React__namespace.Component {
|
|
|
17777
17778
|
}, /*#__PURE__*/React__namespace.createElement(ImageLoader, {
|
|
17778
17779
|
src: imageUrl,
|
|
17779
17780
|
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
|
-
,
|
|
17781
|
+
onUpdate: this.handleUpdate,
|
|
17783
17782
|
preloader: preloader,
|
|
17784
17783
|
imgProps: imageProps
|
|
17785
17784
|
}), graphie, extraGraphie);
|
|
@@ -17791,9 +17790,7 @@ class SvgImage extends React__namespace.Component {
|
|
|
17791
17790
|
}, /*#__PURE__*/React__namespace.createElement(ImageLoader, {
|
|
17792
17791
|
src: imageUrl,
|
|
17793
17792
|
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
|
-
,
|
|
17793
|
+
onUpdate: this.handleUpdate,
|
|
17797
17794
|
preloader: preloader,
|
|
17798
17795
|
imgProps: imageProps
|
|
17799
17796
|
}), graphie);
|
|
@@ -18371,33 +18368,33 @@ class Lint extends React__namespace.Component {
|
|
|
18371
18368
|
let warningText;
|
|
18372
18369
|
let warningTextStyle;
|
|
18373
18370
|
if (this.props.severity === Severity.Error) {
|
|
18374
|
-
severityStyle = styles$
|
|
18371
|
+
severityStyle = styles$B.indicatorError;
|
|
18375
18372
|
warningText = "Error";
|
|
18376
|
-
warningTextStyle = styles$
|
|
18373
|
+
warningTextStyle = styles$B.publishBlockingError;
|
|
18377
18374
|
} else if (this.props.severity === Severity.Warning) {
|
|
18378
|
-
severityStyle = styles$
|
|
18375
|
+
severityStyle = styles$B.indicatorWarning;
|
|
18379
18376
|
warningText = "Warning";
|
|
18380
|
-
warningTextStyle = styles$
|
|
18377
|
+
warningTextStyle = styles$B.warning;
|
|
18381
18378
|
} else {
|
|
18382
|
-
severityStyle = styles$
|
|
18379
|
+
severityStyle = styles$B.indicatorGuideline;
|
|
18383
18380
|
warningText = "Recommendation";
|
|
18384
|
-
warningTextStyle = styles$
|
|
18381
|
+
warningTextStyle = styles$B.warning;
|
|
18385
18382
|
}
|
|
18386
18383
|
return /*#__PURE__*/React__namespace.createElement("a", {
|
|
18387
18384
|
href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
|
|
18388
18385
|
target: "lint-help-window",
|
|
18389
18386
|
className: aphrodite.css(style)
|
|
18390
18387
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
18391
|
-
className: aphrodite.css(styles$
|
|
18388
|
+
className: aphrodite.css(styles$B.indicator, severityStyle)
|
|
18392
18389
|
}, this.props.severity === 1 && /*#__PURE__*/React__namespace.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React__namespace.createElement("div", {
|
|
18393
|
-
className: aphrodite.css(styles$
|
|
18390
|
+
className: aphrodite.css(styles$B.tooltip, tooltipAbove && styles$B.tooltipAbove)
|
|
18394
18391
|
}, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React__namespace.createElement("p", {
|
|
18395
18392
|
key: i,
|
|
18396
|
-
className: aphrodite.css(styles$
|
|
18393
|
+
className: aphrodite.css(styles$B.tooltipParagraph)
|
|
18397
18394
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
18398
18395
|
className: aphrodite.css(warningTextStyle)
|
|
18399
18396
|
}, warningText, ":", " "), m)), /*#__PURE__*/React__namespace.createElement("div", {
|
|
18400
|
-
className: aphrodite.css(styles$
|
|
18397
|
+
className: aphrodite.css(styles$B.tail, tooltipAbove && styles$B.tailAbove)
|
|
18401
18398
|
})));
|
|
18402
18399
|
};
|
|
18403
18400
|
|
|
@@ -18425,20 +18422,20 @@ class Lint extends React__namespace.Component {
|
|
|
18425
18422
|
}
|
|
18426
18423
|
if (blockHighlight) {
|
|
18427
18424
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
18428
|
-
className: aphrodite.css(styles$
|
|
18429
|
-
}, this.renderLink(styles$
|
|
18425
|
+
className: aphrodite.css(styles$B.lintContainer, styles$B.lintContainerBlock)
|
|
18426
|
+
}, this.renderLink(styles$B.radioWidgetHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
|
|
18430
18427
|
}
|
|
18431
18428
|
if (inline) {
|
|
18432
18429
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
18433
|
-
className: aphrodite.css(styles$
|
|
18434
|
-
}, this.renderLink(styles$
|
|
18430
|
+
className: aphrodite.css(styles$B.lintContainer)
|
|
18431
|
+
}, this.renderLink(styles$B.inlineHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
|
|
18435
18432
|
}
|
|
18436
18433
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
18437
|
-
className: aphrodite.css(styles$
|
|
18438
|
-
}, this.renderLink(styles$
|
|
18434
|
+
className: aphrodite.css(styles$B.lintContainer)
|
|
18435
|
+
}, this.renderLink(styles$B.hoverTarget), /*#__PURE__*/React__namespace.createElement("div", null, children));
|
|
18439
18436
|
}
|
|
18440
18437
|
}
|
|
18441
|
-
const styles$
|
|
18438
|
+
const styles$B = aphrodite.StyleSheet.create({
|
|
18442
18439
|
// This is the class of the outermost element.
|
|
18443
18440
|
// We use relative positioning so that the lint indicator can be
|
|
18444
18441
|
// positioned absolutely relative to the position of the linty container.
|
|
@@ -19132,15 +19129,17 @@ class TranslationLinter {
|
|
|
19132
19129
|
}
|
|
19133
19130
|
|
|
19134
19131
|
/**
|
|
19135
|
-
* Preprocess TeX code to convert things that
|
|
19132
|
+
* Preprocess TeX code to convert things that MathJax doesn't know how to handle
|
|
19136
19133
|
* to things is does.
|
|
19137
19134
|
*/
|
|
19138
|
-
|
|
19139
19135
|
var preprocessTex = (texCode => texCode
|
|
19140
19136
|
// Replace uses of \begin{align}...\end{align} which KaTeX doesn't
|
|
19141
19137
|
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
19142
19138
|
// the same is supported by KaTeX. It does the same for align*.
|
|
19143
19139
|
// TODO(kevinb) update content to use aligned instead of align.
|
|
19140
|
+
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
19141
|
+
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
19142
|
+
// "aligned").
|
|
19144
19143
|
.replace(/\{align[*]?\}/g, "{aligned}")
|
|
19145
19144
|
// Replace non-breaking spaces with regular spaces.
|
|
19146
19145
|
.replace(/[\u00a0]/g, " "));
|
|
@@ -20574,7 +20573,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20574
20573
|
};
|
|
20575
20574
|
const mobileInnerStyle = {
|
|
20576
20575
|
...innerStyle,
|
|
20577
|
-
...styles$
|
|
20576
|
+
...styles$A.mobileZoomableParentFix
|
|
20578
20577
|
};
|
|
20579
20578
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
20580
20579
|
key: state.key,
|
|
@@ -20608,6 +20607,9 @@ class Renderer extends React__namespace.Component {
|
|
|
20608
20607
|
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
20609
20608
|
// the same is supported by KaTeX. It does the same for align*.
|
|
20610
20609
|
// TODO(kevinb) update content to use aligned instead of align.
|
|
20610
|
+
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
20611
|
+
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
20612
|
+
// "aligned").
|
|
20611
20613
|
const tex = node.content.replace(/\{align[*]?\}/g, "{aligned}");
|
|
20612
20614
|
|
|
20613
20615
|
// We render math here instead of in perseus-markdown.jsx
|
|
@@ -20711,7 +20713,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20711
20713
|
};
|
|
20712
20714
|
const mobileInnerStyle = {
|
|
20713
20715
|
...innerStyle,
|
|
20714
|
-
...styles$
|
|
20716
|
+
...styles$A.mobileZoomableParentFix
|
|
20715
20717
|
};
|
|
20716
20718
|
const wrappedOutput = /*#__PURE__*/React__namespace.createElement("div", {
|
|
20717
20719
|
style: {
|
|
@@ -21219,7 +21221,7 @@ class Renderer extends React__namespace.Component {
|
|
|
21219
21221
|
return this.lastRenderedMarkdown;
|
|
21220
21222
|
}
|
|
21221
21223
|
}
|
|
21222
|
-
const styles$
|
|
21224
|
+
const styles$A = {
|
|
21223
21225
|
mobileZoomableParentFix: {
|
|
21224
21226
|
// NOTE(abdul): There is an issue where transform animations will
|
|
21225
21227
|
// cause the Zoomable component to disappear when running on the
|
|
@@ -21265,28 +21267,24 @@ class TextInput extends React__namespace.Component {
|
|
|
21265
21267
|
style
|
|
21266
21268
|
} = this.props;
|
|
21267
21269
|
const formattedValue = value === null ? "" : value.toString();
|
|
21268
|
-
return (
|
|
21269
|
-
|
|
21270
|
-
|
|
21271
|
-
|
|
21272
|
-
|
|
21273
|
-
|
|
21274
|
-
|
|
21275
|
-
|
|
21276
|
-
|
|
21277
|
-
|
|
21278
|
-
|
|
21279
|
-
|
|
21280
|
-
|
|
21281
|
-
|
|
21282
|
-
|
|
21283
|
-
|
|
21284
|
-
|
|
21285
|
-
|
|
21286
|
-
autoCapitalize: "off",
|
|
21287
|
-
autoComplete: "off"
|
|
21288
|
-
})
|
|
21289
|
-
);
|
|
21270
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextField, {
|
|
21271
|
+
style: style,
|
|
21272
|
+
disabled: disabled,
|
|
21273
|
+
id: this.id,
|
|
21274
|
+
value: formattedValue,
|
|
21275
|
+
type: "text",
|
|
21276
|
+
"aria-label": labelText,
|
|
21277
|
+
onChange: value => this.props.onChange(value),
|
|
21278
|
+
placeholder: placeholder,
|
|
21279
|
+
onFocus: onFocus,
|
|
21280
|
+
onBlur: onBlur,
|
|
21281
|
+
onKeyDown: onKeyDown
|
|
21282
|
+
// @ts-expect-error - TS2322 - Type '{ style: StyleType; disabled: boolean | undefined; id: string; value: string; type: "text"; "aria-label": string | undefined; onChange: (value: string) => void; placeholder: string | undefined; ... 5 more ...; autoComplete: string; }' is not assignable to type 'IntrinsicAttributes & ExportProps & RefAttributes<HTMLInputElement>'.
|
|
21283
|
+
,
|
|
21284
|
+
autoCorrect: "off",
|
|
21285
|
+
autoCapitalize: "off",
|
|
21286
|
+
autoComplete: "off"
|
|
21287
|
+
});
|
|
21290
21288
|
}
|
|
21291
21289
|
focus = () => {
|
|
21292
21290
|
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
@@ -22019,10 +22017,10 @@ class InputNumber extends React__namespace.Component {
|
|
|
22019
22017
|
// Note: This is _very_ similar to what `numeric-input.jsx` does. If
|
|
22020
22018
|
// you modify this, double-check if you also need to modify that
|
|
22021
22019
|
// component.
|
|
22022
|
-
const inputStyles = [styles$
|
|
22020
|
+
const inputStyles = [styles$z.default, this.props.size === "small" ? styles$z.small : null, this.props.rightAlign ? styles$z.rightAlign : styles$z.leftAlign];
|
|
22023
22021
|
// Unanswered
|
|
22024
22022
|
if (rubric && !this.props.currentValue) {
|
|
22025
|
-
inputStyles.push(styles$
|
|
22023
|
+
inputStyles.push(styles$z.answerStateUnanswered);
|
|
22026
22024
|
}
|
|
22027
22025
|
return /*#__PURE__*/React__namespace.createElement(InputWithExamples
|
|
22028
22026
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -22162,7 +22160,7 @@ class InputNumber extends React__namespace.Component {
|
|
|
22162
22160
|
return answerString;
|
|
22163
22161
|
}
|
|
22164
22162
|
}
|
|
22165
|
-
const styles$
|
|
22163
|
+
const styles$z = aphrodite.StyleSheet.create({
|
|
22166
22164
|
default: {
|
|
22167
22165
|
width: 80,
|
|
22168
22166
|
height: "auto"
|
|
@@ -23155,7 +23153,7 @@ const FocusRing = function (props) {
|
|
|
23155
23153
|
};
|
|
23156
23154
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
23157
23155
|
"data-testid": "focus-ring",
|
|
23158
|
-
className: aphrodite.css(styles$
|
|
23156
|
+
className: aphrodite.css(styles$y.ring),
|
|
23159
23157
|
style: style
|
|
23160
23158
|
}, children);
|
|
23161
23159
|
};
|
|
@@ -23164,7 +23162,7 @@ FocusRing.defaultProps = {
|
|
|
23164
23162
|
color: kaGreen$1,
|
|
23165
23163
|
multipleSelect: false
|
|
23166
23164
|
};
|
|
23167
|
-
const styles$
|
|
23165
|
+
const styles$y = aphrodite.StyleSheet.create({
|
|
23168
23166
|
ring: {
|
|
23169
23167
|
margin: "auto",
|
|
23170
23168
|
display: "inline-block",
|
|
@@ -23191,7 +23189,7 @@ function getChoiceLetter(pos, strings) {
|
|
|
23191
23189
|
}
|
|
23192
23190
|
|
|
23193
23191
|
const CHOICE_ICON_SIZE = 24;
|
|
23194
|
-
const styles$
|
|
23192
|
+
const styles$x = aphrodite.StyleSheet.create({
|
|
23195
23193
|
iconWrapper: {
|
|
23196
23194
|
display: "inline-block",
|
|
23197
23195
|
position: "relative"
|
|
@@ -23214,7 +23212,7 @@ const CrossOutLine = function (props) {
|
|
|
23214
23212
|
width: CROSS_OUT_LINE_SIZE,
|
|
23215
23213
|
height: CROSS_OUT_LINE_SIZE,
|
|
23216
23214
|
viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
|
|
23217
|
-
className: aphrodite.css(styles$
|
|
23215
|
+
className: aphrodite.css(styles$w.crossOutLine),
|
|
23218
23216
|
"data-testid": "choice-icon__cross-out-line"
|
|
23219
23217
|
}, /*#__PURE__*/React__namespace.createElement("line", {
|
|
23220
23218
|
// The line stretches from the bottom-left to top-right.
|
|
@@ -23229,7 +23227,7 @@ const CrossOutLine = function (props) {
|
|
|
23229
23227
|
strokeLinecap: "round"
|
|
23230
23228
|
}));
|
|
23231
23229
|
};
|
|
23232
|
-
const styles$
|
|
23230
|
+
const styles$w = aphrodite.StyleSheet.create({
|
|
23233
23231
|
crossOutLine: {
|
|
23234
23232
|
// Center the icon within the container.
|
|
23235
23233
|
position: "absolute",
|
|
@@ -23313,7 +23311,7 @@ const ChoiceIcon = function (props) {
|
|
|
23313
23311
|
} = props;
|
|
23314
23312
|
const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
|
|
23315
23313
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
23316
|
-
className: aphrodite.css(styles$
|
|
23314
|
+
className: aphrodite.css(styles$x.iconWrapper)
|
|
23317
23315
|
}, /*#__PURE__*/React__namespace.createElement(FocusRing, {
|
|
23318
23316
|
color: wonderBlocksTokens.color.blue,
|
|
23319
23317
|
visible: focused || hovered,
|
|
@@ -23322,13 +23320,13 @@ const ChoiceIcon = function (props) {
|
|
|
23322
23320
|
// @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
23321
|
style: dynamicStyles,
|
|
23324
23322
|
"data-testid": "choice-icon__library-choice-icon",
|
|
23325
|
-
className: aphrodite.css(styles$
|
|
23323
|
+
className: aphrodite.css(styles$v.circle, showCorrectness && correct && styles$v.circleCorrect, showCorrectness && !correct && styles$v.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$v.circleIncorrectAnswered)
|
|
23326
23324
|
// used in BaseRadio editMode to check
|
|
23327
23325
|
// if we actually clicked on the radio icon
|
|
23328
23326
|
,
|
|
23329
23327
|
"data-is-radio-icon": true
|
|
23330
23328
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
23331
|
-
className: aphrodite.css(styles$
|
|
23329
|
+
className: aphrodite.css(styles$v.innerWrapper)
|
|
23332
23330
|
}, /*#__PURE__*/React__namespace.createElement(ChoiceInner, {
|
|
23333
23331
|
pos: pos,
|
|
23334
23332
|
showCorrectness: showCorrectness,
|
|
@@ -23337,7 +23335,7 @@ const ChoiceIcon = function (props) {
|
|
|
23337
23335
|
color: dynamicStyles.borderColor
|
|
23338
23336
|
}));
|
|
23339
23337
|
};
|
|
23340
|
-
const styles$
|
|
23338
|
+
const styles$v = aphrodite.StyleSheet.create({
|
|
23341
23339
|
innerWrapper: {
|
|
23342
23340
|
width: CHOICE_ICON_SIZE,
|
|
23343
23341
|
height: CHOICE_ICON_SIZE,
|
|
@@ -23432,19 +23430,19 @@ const OptionStatus = function (props) {
|
|
|
23432
23430
|
}
|
|
23433
23431
|
let textStyle;
|
|
23434
23432
|
if (correct) {
|
|
23435
|
-
textStyle = styles$
|
|
23433
|
+
textStyle = styles$u.correct;
|
|
23436
23434
|
} else {
|
|
23437
23435
|
if (checked || previouslyAnswered) {
|
|
23438
|
-
textStyle = styles$
|
|
23436
|
+
textStyle = styles$u.incorrectAnswered;
|
|
23439
23437
|
} else {
|
|
23440
|
-
textStyle = styles$
|
|
23438
|
+
textStyle = styles$u.incorrect;
|
|
23441
23439
|
}
|
|
23442
23440
|
}
|
|
23443
23441
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
23444
|
-
className: aphrodite.css(styles$
|
|
23442
|
+
className: aphrodite.css(styles$u.text, textStyle)
|
|
23445
23443
|
}, renderText(checked, correct, crossedOut, strings));
|
|
23446
23444
|
};
|
|
23447
|
-
const styles$
|
|
23445
|
+
const styles$u = aphrodite.StyleSheet.create({
|
|
23448
23446
|
text: {
|
|
23449
23447
|
alignItems: "center",
|
|
23450
23448
|
display: "flex",
|
|
@@ -23513,8 +23511,8 @@ const Choice = function (props) {
|
|
|
23513
23511
|
crossedOut: updatedCrossedOut
|
|
23514
23512
|
});
|
|
23515
23513
|
}
|
|
23516
|
-
const descriptionClassName = classNames__default["default"]("description", aphrodite.css(styles$
|
|
23517
|
-
const rationaleClassName = classNames__default["default"]("perseus-radio-rationale-content", aphrodite.css(styles$
|
|
23514
|
+
const descriptionClassName = classNames__default["default"]("description", aphrodite.css(styles$t.description));
|
|
23515
|
+
const rationaleClassName = classNames__default["default"]("perseus-radio-rationale-content", aphrodite.css(styles$t.rationale));
|
|
23518
23516
|
|
|
23519
23517
|
// We want to show the choices as dimmed out when the choices are disabled.
|
|
23520
23518
|
// However, we don't want to do this when we're in review mode in the
|
|
@@ -23681,7 +23679,7 @@ const Choice = function (props) {
|
|
|
23681
23679
|
"data-testid": `perseus-radio-rationale-content-${pos}`
|
|
23682
23680
|
}, rationale));
|
|
23683
23681
|
};
|
|
23684
|
-
const styles$
|
|
23682
|
+
const styles$t = aphrodite.StyleSheet.create({
|
|
23685
23683
|
description: {
|
|
23686
23684
|
display: "inline-block",
|
|
23687
23685
|
width: "100%"
|
|
@@ -23880,10 +23878,10 @@ const BaseRadio = function (props) {
|
|
|
23880
23878
|
const isMobile = apiOptions.isMobile;
|
|
23881
23879
|
const firstChoiceHighlighted = choices[0].highlighted;
|
|
23882
23880
|
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$
|
|
23881
|
+
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));
|
|
23882
|
+
const instructionsClassName = classNames__default["default"]("instructions", aphrodite.css(styles$s.instructions, isMobile && styles$s.instructionsMobile));
|
|
23885
23883
|
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect, strings);
|
|
23886
|
-
const responsiveClassName = aphrodite.css(styles$
|
|
23884
|
+
const responsiveClassName = aphrodite.css(styles$s.responsiveFieldset);
|
|
23887
23885
|
const fieldset = /*#__PURE__*/React__namespace.createElement("fieldset", {
|
|
23888
23886
|
className: `perseus-widget-radio-fieldset ${responsiveClassName}`
|
|
23889
23887
|
}, /*#__PURE__*/React__namespace.createElement("legend", {
|
|
@@ -23934,7 +23932,7 @@ const BaseRadio = function (props) {
|
|
|
23934
23932
|
const aphroditeClassName = checked => {
|
|
23935
23933
|
// Whether or not to show correctness borders
|
|
23936
23934
|
// for this choice and the next choice.
|
|
23937
|
-
return aphrodite.css(sharedStyles.aboveScratchpad, styles$
|
|
23935
|
+
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
23936
|
};
|
|
23939
23937
|
|
|
23940
23938
|
// HACK(abdulrahman): Preloads the selection-state
|
|
@@ -24008,14 +24006,14 @@ const BaseRadio = function (props) {
|
|
|
24008
24006
|
// Allow for horizontal scrolling if content is too wide, which may be
|
|
24009
24007
|
// an issue especially on phones.
|
|
24010
24008
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
24011
|
-
className: aphrodite.css(styles$
|
|
24009
|
+
className: aphrodite.css(styles$s.responsiveContainer)
|
|
24012
24010
|
}, fieldset);
|
|
24013
24011
|
};
|
|
24014
24012
|
BaseRadio.defaultProps = {
|
|
24015
24013
|
editMode: false,
|
|
24016
24014
|
multipleSelect: false
|
|
24017
24015
|
};
|
|
24018
|
-
const styles$
|
|
24016
|
+
const styles$s = aphrodite.StyleSheet.create({
|
|
24019
24017
|
instructions: {
|
|
24020
24018
|
display: "block",
|
|
24021
24019
|
color: gray17,
|
|
@@ -24699,9 +24697,9 @@ class Categorizer extends React__namespace.Component {
|
|
|
24699
24697
|
indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
|
|
24700
24698
|
}
|
|
24701
24699
|
const table = /*#__PURE__*/React__namespace.createElement("table", {
|
|
24702
|
-
className: "categorizer-table " + aphrodite.css(styles$
|
|
24700
|
+
className: "categorizer-table " + aphrodite.css(styles$r.mobileTable)
|
|
24703
24701
|
}, /*#__PURE__*/React__namespace.createElement("thead", null, /*#__PURE__*/React__namespace.createElement("tr", null, /*#__PURE__*/React__namespace.createElement("td", {
|
|
24704
|
-
className: aphrodite.css(styles$
|
|
24702
|
+
className: aphrodite.css(styles$r.emptyHeaderCell)
|
|
24705
24703
|
}), this.props.categories.map((category, i) => {
|
|
24706
24704
|
// Array index is the correct key here, as that's
|
|
24707
24705
|
// how category grading actually works -- no way
|
|
@@ -24709,7 +24707,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24709
24707
|
// middle. (If we later add that, this should be
|
|
24710
24708
|
// fixed.)
|
|
24711
24709
|
return /*#__PURE__*/React__namespace.createElement("th", {
|
|
24712
|
-
className: aphrodite.css(styles$
|
|
24710
|
+
className: aphrodite.css(styles$r.header),
|
|
24713
24711
|
key: i
|
|
24714
24712
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
24715
24713
|
content: category,
|
|
@@ -24731,7 +24729,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24731
24729
|
})), self.props.categories.map((catName, catNum) => {
|
|
24732
24730
|
const selected = self.props.values[itemNum] === catNum;
|
|
24733
24731
|
return /*#__PURE__*/React__namespace.createElement("td", {
|
|
24734
|
-
className: "category " + aphrodite.css(styles$
|
|
24732
|
+
className: "category " + aphrodite.css(styles$r.cell),
|
|
24735
24733
|
key: catNum
|
|
24736
24734
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
24737
24735
|
className: ClassNames.INTERACTIVE,
|
|
@@ -24746,7 +24744,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24746
24744
|
onChange: () => this.onChange(itemNum, catNum),
|
|
24747
24745
|
onClick: e => e.stopPropagation()
|
|
24748
24746
|
}), !isMobile && /*#__PURE__*/React__namespace.createElement("span", {
|
|
24749
|
-
className: aphrodite.css(styles$
|
|
24747
|
+
className: aphrodite.css(styles$r.radioSpan, selected && styles$r.checkedRadioSpan, this.props.static && selected && styles$r.staticCheckedRadioSpan)
|
|
24750
24748
|
}, selected ? /*#__PURE__*/React__namespace.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React__namespace.createElement(InlineIcon, iconCircleThin))));
|
|
24751
24749
|
}));
|
|
24752
24750
|
/* eslint-enable max-len */
|
|
@@ -24758,7 +24756,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24758
24756
|
"categorizer-container": true,
|
|
24759
24757
|
"static-mode": this.props.static
|
|
24760
24758
|
});
|
|
24761
|
-
const inlineStyles = this.props.apiOptions.isMobile ? [styles$
|
|
24759
|
+
const inlineStyles = this.props.apiOptions.isMobile ? [styles$r.fullBleedContainer] : [];
|
|
24762
24760
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
24763
24761
|
className: extraClassNames + " " + aphrodite.css(...inlineStyles)
|
|
24764
24762
|
}, table);
|
|
@@ -24807,7 +24805,7 @@ const pageMargin = 16;
|
|
|
24807
24805
|
|
|
24808
24806
|
// Stylesheets aren't directly testable
|
|
24809
24807
|
/* c8 ignore next */
|
|
24810
|
-
const styles$
|
|
24808
|
+
const styles$r = aphrodite.StyleSheet.create({
|
|
24811
24809
|
mobileTable: {
|
|
24812
24810
|
[mediaQueries.smOrSmaller]: {
|
|
24813
24811
|
minWidth: "auto"
|
|
@@ -25070,7 +25068,7 @@ class CSProgram extends React__namespace.Component {
|
|
|
25070
25068
|
// creator "went wild".
|
|
25071
25069
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
25072
25070
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25073
|
-
className: aphrodite.css(styles$
|
|
25071
|
+
className: aphrodite.css(styles$q.widthOverride, styleContainer && styles$q.container)
|
|
25074
25072
|
}, /*#__PURE__*/React__namespace.createElement("iframe", {
|
|
25075
25073
|
sandbox: sandboxOptions,
|
|
25076
25074
|
src: url,
|
|
@@ -25080,7 +25078,7 @@ class CSProgram extends React__namespace.Component {
|
|
|
25080
25078
|
}));
|
|
25081
25079
|
}
|
|
25082
25080
|
}
|
|
25083
|
-
const styles$
|
|
25081
|
+
const styles$q = aphrodite.StyleSheet.create({
|
|
25084
25082
|
// Override the inherited width from the perseus paragraph class
|
|
25085
25083
|
// 820 is minimum width for 420px editor and 400px canvas
|
|
25086
25084
|
widthOverride: {
|
|
@@ -25127,7 +25125,7 @@ class Definition extends React__namespace.Component {
|
|
|
25127
25125
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.Popover, {
|
|
25128
25126
|
content: /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
|
|
25129
25127
|
color: "white",
|
|
25130
|
-
style: styles$
|
|
25128
|
+
style: styles$p.tooltipBody,
|
|
25131
25129
|
closeButtonVisible: true
|
|
25132
25130
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
25133
25131
|
apiOptions: this.props.apiOptions,
|
|
@@ -25159,7 +25157,7 @@ class Definition extends React__namespace.Component {
|
|
|
25159
25157
|
});
|
|
25160
25158
|
}
|
|
25161
25159
|
}
|
|
25162
|
-
const styles$
|
|
25160
|
+
const styles$p = {
|
|
25163
25161
|
tooltipBody: {
|
|
25164
25162
|
color: wonderBlocksTokens.color.offBlack,
|
|
25165
25163
|
fontSize: 20,
|
|
@@ -25386,7 +25384,7 @@ class Explanation extends React__namespace.Component {
|
|
|
25386
25384
|
marginRight: "-6px",
|
|
25387
25385
|
"white-space": "normal"
|
|
25388
25386
|
};
|
|
25389
|
-
const contentStyling = [styles$
|
|
25387
|
+
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
25388
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.UniqueIDProvider, {
|
|
25391
25389
|
mockOnFirstRender: true,
|
|
25392
25390
|
scope: "explanation-widget"
|
|
@@ -25405,7 +25403,7 @@ class Explanation extends React__namespace.Component {
|
|
|
25405
25403
|
"aria-hidden": !this.state.expanded,
|
|
25406
25404
|
testId: "content-container"
|
|
25407
25405
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
25408
|
-
style: styles$
|
|
25406
|
+
style: styles$o.contentWrapper
|
|
25409
25407
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
25410
25408
|
apiOptions: this.props.apiOptions,
|
|
25411
25409
|
content: this.props.explanation,
|
|
@@ -25424,7 +25422,7 @@ class Explanation extends React__namespace.Component {
|
|
|
25424
25422
|
const leftBorderSpacing = 23;
|
|
25425
25423
|
const verticalContentPadding = 10;
|
|
25426
25424
|
const arrowHeight = 14;
|
|
25427
|
-
const styles$
|
|
25425
|
+
const styles$o = aphrodite.StyleSheet.create({
|
|
25428
25426
|
content: {
|
|
25429
25427
|
borderLeft: "0px solid #ccc",
|
|
25430
25428
|
display: "inline-grid",
|
|
@@ -25490,15 +25488,15 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
25490
25488
|
nextQuestion
|
|
25491
25489
|
} = this.context.strings;
|
|
25492
25490
|
const answerBarStyle = {
|
|
25493
|
-
...styles$
|
|
25491
|
+
...styles$n.answerBar,
|
|
25494
25492
|
backgroundColor: answerBarState === "CORRECT" ? wonderBlocksTokens.color.offWhite : "white",
|
|
25495
25493
|
// Center the "Correct!" message only when there's no next question
|
|
25496
25494
|
justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
|
|
25497
25495
|
};
|
|
25498
25496
|
const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React__namespace.createElement("span", {
|
|
25499
|
-
style: styles$
|
|
25497
|
+
style: styles$n.text
|
|
25500
25498
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
25501
|
-
style: styles$
|
|
25499
|
+
style: styles$n.tryAgainIcon
|
|
25502
25500
|
}, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React__namespace.createElement("span", {
|
|
25503
25501
|
style: {
|
|
25504
25502
|
marginLeft: 8
|
|
@@ -25517,7 +25515,7 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
25517
25515
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25518
25516
|
style: answerBarStyle
|
|
25519
25517
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
25520
|
-
style: styles$
|
|
25518
|
+
style: styles$n.text
|
|
25521
25519
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
25522
25520
|
style: {
|
|
25523
25521
|
fontSize: 28,
|
|
@@ -25539,7 +25537,7 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
25539
25537
|
}
|
|
25540
25538
|
}
|
|
25541
25539
|
const fontSize = 17;
|
|
25542
|
-
const styles$
|
|
25540
|
+
const styles$n = {
|
|
25543
25541
|
answerBar: {
|
|
25544
25542
|
display: "flex",
|
|
25545
25543
|
alignItems: "center",
|
|
@@ -25739,7 +25737,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25739
25737
|
}));
|
|
25740
25738
|
gradeStatus = this.context.strings.incorrect;
|
|
25741
25739
|
}
|
|
25742
|
-
const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$
|
|
25740
|
+
const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$m.gradedGroupInSet) : aphrodite.css(styles$m.gradedGroup);
|
|
25743
25741
|
const classes = classNames__default["default"]({
|
|
25744
25742
|
[mobileClass]: apiOptions.isMobile,
|
|
25745
25743
|
"perseus-graded-group": true,
|
|
@@ -25758,7 +25756,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25758
25756
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25759
25757
|
className: classes
|
|
25760
25758
|
}, !!this.props.title && /*#__PURE__*/React__namespace.createElement("div", {
|
|
25761
|
-
className: aphrodite.css(styles$
|
|
25759
|
+
className: aphrodite.css(styles$m.title)
|
|
25762
25760
|
}, this.props.title), /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, this.props, {
|
|
25763
25761
|
// eslint-disable-next-line react/no-string-refs
|
|
25764
25762
|
ref: "renderer",
|
|
@@ -25792,7 +25790,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25792
25790
|
}, 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
25791
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
25794
25792
|
tabIndex: "0",
|
|
25795
|
-
className: aphrodite.css(styles$
|
|
25793
|
+
className: aphrodite.css(styles$m.explanationTitle),
|
|
25796
25794
|
onClick: () => this.setState({
|
|
25797
25795
|
showHint: false
|
|
25798
25796
|
}),
|
|
@@ -25825,7 +25823,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25825
25823
|
showHint: true
|
|
25826
25824
|
});
|
|
25827
25825
|
},
|
|
25828
|
-
className: aphrodite.css(styles$
|
|
25826
|
+
className: aphrodite.css(styles$m.showHintLink)
|
|
25829
25827
|
}, this.context.strings.explain)), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React__namespace.createElement(GradedGroupAnswerBar, {
|
|
25830
25828
|
apiOptions: apiOptions,
|
|
25831
25829
|
answerBarState: answerBarState,
|
|
@@ -25837,7 +25835,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25837
25835
|
const traverseChildWidgets$2 = function (props, traverseRenderer) {
|
|
25838
25836
|
return ___default["default"].extend({}, props, traverseRenderer(props));
|
|
25839
25837
|
};
|
|
25840
|
-
const styles$
|
|
25838
|
+
const styles$m = aphrodite.StyleSheet.create({
|
|
25841
25839
|
gradedGroupInSet: {
|
|
25842
25840
|
// Reset a few desktop-only styles that come from graded-group.less
|
|
25843
25841
|
marginLeft: 0,
|
|
@@ -25908,20 +25906,20 @@ class Indicators extends React__namespace.Component {
|
|
|
25908
25906
|
return /*#__PURE__*/React__namespace.createElement("ul", {
|
|
25909
25907
|
// reduntantly add class name for use in .less files--
|
|
25910
25908
|
// the styles object key gets hashed
|
|
25911
|
-
className: classNames__default["default"](aphrodite.css(styles$
|
|
25909
|
+
className: classNames__default["default"](aphrodite.css(styles$l.indicatorContainer), "indicatorContainer")
|
|
25912
25910
|
}, this.props.gradedGroups.map((_ref, i) => {
|
|
25913
25911
|
let {
|
|
25914
25912
|
title
|
|
25915
25913
|
} = _ref;
|
|
25916
25914
|
return /*#__PURE__*/React__namespace.createElement("li", {
|
|
25917
|
-
className: aphrodite.css(styles$
|
|
25915
|
+
className: aphrodite.css(styles$l.indicator),
|
|
25918
25916
|
key: title
|
|
25919
25917
|
}, /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
25920
25918
|
role: "button",
|
|
25921
25919
|
"aria-label": this.context.strings.skipToTitle({
|
|
25922
25920
|
title
|
|
25923
25921
|
}),
|
|
25924
|
-
style: styles$
|
|
25922
|
+
style: styles$l.indicatorButton,
|
|
25925
25923
|
onClick: () => this.props.onChangeCurrentGroup(i),
|
|
25926
25924
|
onKeyDown: e => this.handleKeyDown(e, i)
|
|
25927
25925
|
}, _ref2 => {
|
|
@@ -25931,9 +25929,9 @@ class Indicators extends React__namespace.Component {
|
|
|
25931
25929
|
pressed
|
|
25932
25930
|
} = _ref2;
|
|
25933
25931
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
25934
|
-
style: [styles$
|
|
25932
|
+
style: [styles$l.indicatorDot, (hovered || focused || pressed) && styles$l.indicatorDotFocused]
|
|
25935
25933
|
}, i === this.props.currentGroup && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
25936
|
-
style: styles$
|
|
25934
|
+
style: styles$l.indicatorDotActive
|
|
25937
25935
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
25938
25936
|
className: aphrodite.css(a11y.srOnly)
|
|
25939
25937
|
}, this.context.strings.current)));
|
|
@@ -26009,7 +26007,7 @@ class GradedGroupSet extends React__namespace.Component {
|
|
|
26009
26007
|
} = getDependencies();
|
|
26010
26008
|
if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
|
|
26011
26009
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
26012
|
-
className: aphrodite.css(styles$
|
|
26010
|
+
className: aphrodite.css(styles$l.container)
|
|
26013
26011
|
}, this.props.gradedGroups.map((gradedGroup, i) => {
|
|
26014
26012
|
return (
|
|
26015
26013
|
/*#__PURE__*/
|
|
@@ -26032,13 +26030,13 @@ class GradedGroupSet extends React__namespace.Component {
|
|
|
26032
26030
|
const numGroups = this.props.gradedGroups.length;
|
|
26033
26031
|
const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
|
|
26034
26032
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
26035
|
-
className: aphrodite.css(styles$
|
|
26033
|
+
className: aphrodite.css(styles$l.container)
|
|
26036
26034
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
26037
|
-
className: aphrodite.css(styles$
|
|
26035
|
+
className: aphrodite.css(styles$l.top)
|
|
26038
26036
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
26039
|
-
className: aphrodite.css(styles$
|
|
26037
|
+
className: aphrodite.css(styles$l.title)
|
|
26040
26038
|
}, currentGroup.title), /*#__PURE__*/React__namespace.createElement("div", {
|
|
26041
|
-
className: aphrodite.css(styles$
|
|
26039
|
+
className: aphrodite.css(styles$l.spacer)
|
|
26042
26040
|
}), /*#__PURE__*/React__namespace.createElement(Indicators, {
|
|
26043
26041
|
currentGroup: this.state.currentGroup,
|
|
26044
26042
|
gradedGroups: this.props.gradedGroups,
|
|
@@ -26076,7 +26074,7 @@ var GradedGroupSet$1 = {
|
|
|
26076
26074
|
tracking: "all",
|
|
26077
26075
|
isLintable: true
|
|
26078
26076
|
};
|
|
26079
|
-
const styles$
|
|
26077
|
+
const styles$l = aphrodite.StyleSheet.create({
|
|
26080
26078
|
top: {
|
|
26081
26079
|
display: "flex",
|
|
26082
26080
|
flexDirection: "row"
|
|
@@ -26182,7 +26180,7 @@ class ButtonGroup extends React__namespace.Component {
|
|
|
26182
26180
|
id: "" + i,
|
|
26183
26181
|
ref: "button" + i,
|
|
26184
26182
|
key: "" + i,
|
|
26185
|
-
className: aphrodite.css(styles$
|
|
26183
|
+
className: aphrodite.css(styles$k.buttonStyle, button.value === value && styles$k.selectedStyle),
|
|
26186
26184
|
onClick: () => this.toggleSelect(button.value)
|
|
26187
26185
|
}, button.content || "" + button.value);
|
|
26188
26186
|
});
|
|
@@ -26195,7 +26193,7 @@ class ButtonGroup extends React__namespace.Component {
|
|
|
26195
26193
|
}, buttons);
|
|
26196
26194
|
}
|
|
26197
26195
|
}
|
|
26198
|
-
const styles$
|
|
26196
|
+
const styles$k = aphrodite.StyleSheet.create({
|
|
26199
26197
|
buttonStyle: {
|
|
26200
26198
|
backgroundColor: "white",
|
|
26201
26199
|
border: "1px solid #ccc",
|
|
@@ -26799,7 +26797,7 @@ var util = /*#__PURE__*/Object.freeze({
|
|
|
26799
26797
|
});
|
|
26800
26798
|
|
|
26801
26799
|
// @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
|
|
26802
|
-
const MovablePoint$
|
|
26800
|
+
const MovablePoint$3 = Graphie.MovablePoint;
|
|
26803
26801
|
// @ts-expect-error - TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
26804
26802
|
const MovableLine$2 = Graphie.MovableLine;
|
|
26805
26803
|
function isFlipped(newCoord, oldCoord, line) {
|
|
@@ -26845,7 +26843,7 @@ class FunctionGrapher extends React__namespace.Component {
|
|
|
26845
26843
|
})();
|
|
26846
26844
|
render() {
|
|
26847
26845
|
const pointForCoord = (coord, i) => {
|
|
26848
|
-
return /*#__PURE__*/React__namespace.createElement(MovablePoint$
|
|
26846
|
+
return /*#__PURE__*/React__namespace.createElement(MovablePoint$3, {
|
|
26849
26847
|
key: i,
|
|
26850
26848
|
coord: coord,
|
|
26851
26849
|
static: this.props.static,
|
|
@@ -26982,7 +26980,7 @@ class FunctionGrapher extends React__namespace.Component {
|
|
|
26982
26980
|
}],
|
|
26983
26981
|
normalStyle: dashed,
|
|
26984
26982
|
highlightStyle: dashed
|
|
26985
|
-
}, ___default["default"].map(asymptote, (coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$
|
|
26983
|
+
}, ___default["default"].map(asymptote, (coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$3, {
|
|
26986
26984
|
key: `asymptoteCoord-${i}`,
|
|
26987
26985
|
coord: coord,
|
|
26988
26986
|
static: true,
|
|
@@ -27723,7 +27721,7 @@ const Label = Graphie.Label;
|
|
|
27723
27721
|
// @ts-expect-error - TS2339 - Property 'Line' does not exist on type 'typeof Graphie'.
|
|
27724
27722
|
const Line$2 = Graphie.Line;
|
|
27725
27723
|
// @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
|
|
27726
|
-
const MovablePoint$
|
|
27724
|
+
const MovablePoint$2 = Graphie.MovablePoint;
|
|
27727
27725
|
// @ts-expect-error - TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
27728
27726
|
const MovableLine$1 = Graphie.MovableLine;
|
|
27729
27727
|
// @ts-expect-error - TS2339 - Property 'Plot' does not exist on type 'typeof Graphie'.
|
|
@@ -27977,7 +27975,7 @@ class Interaction extends React__namespace.Component {
|
|
|
27977
27975
|
return [coordX, coordY];
|
|
27978
27976
|
}];
|
|
27979
27977
|
if (element.options.constraint === "snap") {
|
|
27980
|
-
constraints.push(MovablePoint$
|
|
27978
|
+
constraints.push(MovablePoint$2.constraints.snap(element.options.snap));
|
|
27981
27979
|
} else if (element.options.constraint === "x") {
|
|
27982
27980
|
constraints.push(coord => {
|
|
27983
27981
|
return [
|
|
@@ -27999,7 +27997,7 @@ class Interaction extends React__namespace.Component {
|
|
|
27999
27997
|
// TODO(eater): foo_[xyz] are hacky non-props to
|
|
28000
27998
|
// get the component to update when constraints
|
|
28001
27999
|
// change
|
|
28002
|
-
return /*#__PURE__*/React__namespace.createElement(MovablePoint$
|
|
28000
|
+
return /*#__PURE__*/React__namespace.createElement(MovablePoint$2, {
|
|
28003
28001
|
key: element.key,
|
|
28004
28002
|
coord: [
|
|
28005
28003
|
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
@@ -28034,7 +28032,7 @@ class Interaction extends React__namespace.Component {
|
|
|
28034
28032
|
return [coordX, coordY];
|
|
28035
28033
|
}];
|
|
28036
28034
|
if (element.options.constraint === "snap") {
|
|
28037
|
-
constraints.push(MovablePoint$
|
|
28035
|
+
constraints.push(MovablePoint$2.constraints.snap(element.options.snap));
|
|
28038
28036
|
} else if (element.options.constraint === "x") {
|
|
28039
28037
|
constraints.push(coord => {
|
|
28040
28038
|
return [
|
|
@@ -28075,14 +28073,14 @@ class Interaction extends React__namespace.Component {
|
|
|
28075
28073
|
foo_x: element.options.constraint,
|
|
28076
28074
|
foo_y: element.options.constraintFn,
|
|
28077
28075
|
foo_z: element.options.snap
|
|
28078
|
-
}, /*#__PURE__*/React__namespace.createElement(MovablePoint$
|
|
28076
|
+
}, /*#__PURE__*/React__namespace.createElement(MovablePoint$2, {
|
|
28079
28077
|
coord: start,
|
|
28080
28078
|
static: true,
|
|
28081
28079
|
normalStyle: {
|
|
28082
28080
|
stroke: "none",
|
|
28083
28081
|
fill: "none"
|
|
28084
28082
|
}
|
|
28085
|
-
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$
|
|
28083
|
+
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$2, {
|
|
28086
28084
|
coord: end,
|
|
28087
28085
|
static: true,
|
|
28088
28086
|
normalStyle: {
|
|
@@ -28639,7 +28637,7 @@ const defaultGraphConfig = {
|
|
|
28639
28637
|
width: 0,
|
|
28640
28638
|
height: 0,
|
|
28641
28639
|
labels: [],
|
|
28642
|
-
|
|
28640
|
+
disableKeyboardInteraction: false
|
|
28643
28641
|
};
|
|
28644
28642
|
const GraphConfigContext = /*#__PURE__*/React.createContext(defaultGraphConfig);
|
|
28645
28643
|
function useGraphConfig() {
|
|
@@ -28786,6 +28784,30 @@ const segmentsIntersect = (_ref, _ref2) => {
|
|
|
28786
28784
|
}
|
|
28787
28785
|
};
|
|
28788
28786
|
|
|
28787
|
+
// Finds the unique intersection point between two rays. Returns undefined if
|
|
28788
|
+
// there is not exactly one intersection point. The first point in each of the
|
|
28789
|
+
// given ray "segments" should be the initial point of the ray. The second point
|
|
28790
|
+
// can be any arbitrary point on the ray different from the initial point.
|
|
28791
|
+
function findIntersectionOfRays(_ref3, _ref4) {
|
|
28792
|
+
let [[a, b], [c, d]] = _ref3;
|
|
28793
|
+
let [[p, q], [r, s]] = _ref4;
|
|
28794
|
+
// See https://stackoverflow.com/a/24392281/7347484 for an explanation of
|
|
28795
|
+
// the determinant and lambda values.
|
|
28796
|
+
const determinant = (c - a) * (s - q) - (r - p) * (d - b);
|
|
28797
|
+
if (determinant === 0) {
|
|
28798
|
+
return undefined;
|
|
28799
|
+
} else {
|
|
28800
|
+
const lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / determinant;
|
|
28801
|
+
const gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / determinant;
|
|
28802
|
+
if (lambda <= 0 || gamma >= 1) {
|
|
28803
|
+
return undefined;
|
|
28804
|
+
}
|
|
28805
|
+
const initialPoint = [a, b];
|
|
28806
|
+
const direction = mafs.vec.sub([c, d], initialPoint);
|
|
28807
|
+
return mafs.vec.add(initialPoint, mafs.vec.scale(direction, lambda));
|
|
28808
|
+
}
|
|
28809
|
+
}
|
|
28810
|
+
|
|
28789
28811
|
// This file contains helper functions for working with angles.
|
|
28790
28812
|
|
|
28791
28813
|
function convertDegreesToRadians(degrees) {
|
|
@@ -28798,6 +28820,8 @@ function calculateAngleInDegrees(_ref) {
|
|
|
28798
28820
|
let [x, y] = _ref;
|
|
28799
28821
|
return Math.atan2(y, x) * 180 / Math.PI;
|
|
28800
28822
|
}
|
|
28823
|
+
|
|
28824
|
+
// Converts polar coordinates to cartesian. The th(eta) parameter is in degrees.
|
|
28801
28825
|
function polar(r, th) {
|
|
28802
28826
|
if (typeof r === "number") {
|
|
28803
28827
|
r = [r, r];
|
|
@@ -29407,7 +29431,7 @@ const VisibleIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
|
29407
29431
|
width: "24",
|
|
29408
29432
|
height: "24",
|
|
29409
29433
|
viewBox: "0 0 24 24",
|
|
29410
|
-
className: aphrodite.css(styles$
|
|
29434
|
+
className: aphrodite.css(styles$j.icon)
|
|
29411
29435
|
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
29412
29436
|
id: "a",
|
|
29413
29437
|
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 +29462,7 @@ const HiddenIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
|
29438
29462
|
width: "24",
|
|
29439
29463
|
height: "24",
|
|
29440
29464
|
viewBox: "0 0 24 24",
|
|
29441
|
-
className: aphrodite.css(styles$
|
|
29465
|
+
className: aphrodite.css(styles$j.icon)
|
|
29442
29466
|
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
29443
29467
|
id: "a",
|
|
29444
29468
|
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 +29497,20 @@ const HUD = _ref => {
|
|
|
29473
29497
|
let state;
|
|
29474
29498
|
let icon;
|
|
29475
29499
|
if (enabled) {
|
|
29476
|
-
state = styles$
|
|
29500
|
+
state = styles$j.enabled;
|
|
29477
29501
|
icon = /*#__PURE__*/React__namespace.createElement(VisibleIcon, null);
|
|
29478
29502
|
} else {
|
|
29479
|
-
state = styles$
|
|
29503
|
+
state = styles$j.disabled;
|
|
29480
29504
|
icon = /*#__PURE__*/React__namespace.createElement(HiddenIcon, null);
|
|
29481
29505
|
}
|
|
29482
29506
|
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
29483
|
-
className: aphrodite.css(styles$
|
|
29507
|
+
className: aphrodite.css(styles$j.hud, fixedPosition && styles$j.hudFixedPosition, state),
|
|
29484
29508
|
onClick: e => {
|
|
29485
29509
|
onClick();
|
|
29486
29510
|
}
|
|
29487
29511
|
}, icon, message);
|
|
29488
29512
|
};
|
|
29489
|
-
const styles$
|
|
29513
|
+
const styles$j = aphrodite.StyleSheet.create({
|
|
29490
29514
|
hud: {
|
|
29491
29515
|
boxSizing: "border-box",
|
|
29492
29516
|
height: 36,
|
|
@@ -29536,19 +29560,19 @@ const styles$k = aphrodite.StyleSheet.create({
|
|
|
29536
29560
|
}
|
|
29537
29561
|
});
|
|
29538
29562
|
|
|
29539
|
-
const
|
|
29563
|
+
const InfoTipBase = props => {
|
|
29540
29564
|
return /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
29541
29565
|
content: /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.Body, {
|
|
29542
|
-
style: styles$
|
|
29566
|
+
style: styles$i.body
|
|
29543
29567
|
}, props.children),
|
|
29544
29568
|
placement: "right"
|
|
29545
29569
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksIcon.PhosphorIcon, {
|
|
29546
29570
|
size: "small",
|
|
29547
29571
|
icon: questionIcon__default["default"],
|
|
29548
|
-
style: styles$
|
|
29572
|
+
style: styles$i.spacingLeft
|
|
29549
29573
|
}));
|
|
29550
29574
|
};
|
|
29551
|
-
const styles$
|
|
29575
|
+
const styles$i = aphrodite.StyleSheet.create({
|
|
29552
29576
|
spacingLeft: {
|
|
29553
29577
|
marginInlineStart: wonderBlocksTokens.spacing.xxxSmall_4
|
|
29554
29578
|
},
|
|
@@ -29577,7 +29601,7 @@ class InfoTip extends React__namespace.Component {
|
|
|
29577
29601
|
|
|
29578
29602
|
render() {
|
|
29579
29603
|
if (this.state.didMount) {
|
|
29580
|
-
return /*#__PURE__*/React__namespace.createElement(
|
|
29604
|
+
return /*#__PURE__*/React__namespace.createElement(InfoTipBase, this.props);
|
|
29581
29605
|
}
|
|
29582
29606
|
return /*#__PURE__*/React__namespace.createElement("div", null);
|
|
29583
29607
|
}
|
|
@@ -29624,7 +29648,7 @@ class MultiButtonGroup extends React__namespace.Component {
|
|
|
29624
29648
|
id: "" + i,
|
|
29625
29649
|
key: "" + i,
|
|
29626
29650
|
ref: "button" + i,
|
|
29627
|
-
className: aphrodite.css(styles$
|
|
29651
|
+
className: aphrodite.css(styles$h.buttonStyle, selected && styles$h.selectedStyle),
|
|
29628
29652
|
onClick: () => this.toggleSelect(button.value)
|
|
29629
29653
|
}, button.content || "" + button.value);
|
|
29630
29654
|
});
|
|
@@ -29636,7 +29660,7 @@ class MultiButtonGroup extends React__namespace.Component {
|
|
|
29636
29660
|
}, buttons);
|
|
29637
29661
|
}
|
|
29638
29662
|
}
|
|
29639
|
-
const styles$
|
|
29663
|
+
const styles$h = aphrodite.StyleSheet.create({
|
|
29640
29664
|
buttonStyle: {
|
|
29641
29665
|
backgroundColor: "white",
|
|
29642
29666
|
border: "1px solid #ccc",
|
|
@@ -29868,62 +29892,6 @@ class NumberInput extends React__namespace.Component {
|
|
|
29868
29892
|
};
|
|
29869
29893
|
}
|
|
29870
29894
|
|
|
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
29895
|
const truth = () => true;
|
|
29928
29896
|
|
|
29929
29897
|
/* A minor abstraction on top of NumberInput for ranges
|
|
@@ -29982,7 +29950,6 @@ var components = /*#__PURE__*/Object.freeze({
|
|
|
29982
29950
|
MathInput: MathInput,
|
|
29983
29951
|
MultiButtonGroup: MultiButtonGroup,
|
|
29984
29952
|
NumberInput: NumberInput,
|
|
29985
|
-
PropCheckBox: PropCheckBox,
|
|
29986
29953
|
RangeInput: RangeInput,
|
|
29987
29954
|
SvgImage: SvgImage,
|
|
29988
29955
|
TextInput: TextInput,
|
|
@@ -30140,8 +30107,9 @@ const lockedFigureColors = {
|
|
|
30140
30107
|
};
|
|
30141
30108
|
const lockedFigureFillStyles = {
|
|
30142
30109
|
none: 0,
|
|
30143
|
-
|
|
30144
|
-
translucent: 0.4
|
|
30110
|
+
white: 1,
|
|
30111
|
+
translucent: 0.4,
|
|
30112
|
+
solid: 1
|
|
30145
30113
|
};
|
|
30146
30114
|
const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
|
|
30147
30115
|
|
|
@@ -30161,10 +30129,20 @@ const LockedEllipse = props => {
|
|
|
30161
30129
|
fillOpacity: lockedFigureFillStyles[fillStyle],
|
|
30162
30130
|
strokeStyle: strokeStyle,
|
|
30163
30131
|
color: lockedFigureColors[color]
|
|
30132
|
+
// We need to override the svg props if we want to have a
|
|
30133
|
+
// different fill color than the stroke color (specifically,
|
|
30134
|
+
// in the case where the fillStyle is "white").
|
|
30135
|
+
,
|
|
30136
|
+
svgEllipseProps: {
|
|
30137
|
+
style: {
|
|
30138
|
+
fill: fillStyle === "white" ? wonderBlocksTokens.color.white : lockedFigureColors[color]
|
|
30139
|
+
}
|
|
30140
|
+
}
|
|
30164
30141
|
});
|
|
30165
30142
|
};
|
|
30166
30143
|
|
|
30167
30144
|
const LockedFunction = props => {
|
|
30145
|
+
const [equation, setEquation] = React.useState();
|
|
30168
30146
|
const {
|
|
30169
30147
|
color,
|
|
30170
30148
|
strokeStyle,
|
|
@@ -30176,7 +30154,14 @@ const LockedFunction = props => {
|
|
|
30176
30154
|
style: strokeStyle,
|
|
30177
30155
|
domain
|
|
30178
30156
|
};
|
|
30179
|
-
|
|
30157
|
+
React.useEffect(() => {
|
|
30158
|
+
// Parsing the equation in a "useEffect" hook saves about 2ms each frame
|
|
30159
|
+
// when the learner is interacting with the graph (i.e. moving points).
|
|
30160
|
+
setEquation(KAS__namespace.parse(props.equation).expr);
|
|
30161
|
+
}, [props.equation]);
|
|
30162
|
+
if (typeof equation === "undefined") {
|
|
30163
|
+
return null;
|
|
30164
|
+
}
|
|
30180
30165
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
30181
30166
|
className: "locked-function"
|
|
30182
30167
|
}, directionalAxis === "x" && /*#__PURE__*/React__namespace.createElement(mafs.Plot.OfX, _extends({
|
|
@@ -30379,6 +30364,15 @@ const LockedPolygon = props => {
|
|
|
30379
30364
|
fillOpacity: lockedFigureFillStyles[fillStyle],
|
|
30380
30365
|
strokeStyle: strokeStyle,
|
|
30381
30366
|
color: lockedFigureColors[color]
|
|
30367
|
+
// We need to override the svg props if we want to have a
|
|
30368
|
+
// different fill color than the stroke color (specifically,
|
|
30369
|
+
// in the case where the fillStyle is "white").
|
|
30370
|
+
,
|
|
30371
|
+
svgPolygonProps: {
|
|
30372
|
+
style: {
|
|
30373
|
+
fill: fillStyle === "white" ? wonderBlocksTokens.color.white : lockedFigureColors[color]
|
|
30374
|
+
}
|
|
30375
|
+
}
|
|
30382
30376
|
}), showVertices && points.map((point, index) => /*#__PURE__*/React__namespace.createElement(mafs.Point, {
|
|
30383
30377
|
key: `locked-polygon-point-${index}`,
|
|
30384
30378
|
x: point[X],
|
|
@@ -30625,7 +30619,7 @@ function useDraggable(args) {
|
|
|
30625
30619
|
gestureTarget: target,
|
|
30626
30620
|
onMove,
|
|
30627
30621
|
point,
|
|
30628
|
-
|
|
30622
|
+
constrainKeyboardMovement
|
|
30629
30623
|
} = args;
|
|
30630
30624
|
const [dragging, setDragging] = React__namespace.useState(false);
|
|
30631
30625
|
const {
|
|
@@ -30648,6 +30642,7 @@ function useDraggable(args) {
|
|
|
30648
30642
|
event?.stopPropagation();
|
|
30649
30643
|
const isKeyboard = type.includes("key");
|
|
30650
30644
|
if (isKeyboard) {
|
|
30645
|
+
invariant(event instanceof KeyboardEvent);
|
|
30651
30646
|
event?.preventDefault();
|
|
30652
30647
|
|
|
30653
30648
|
// When a key is held down, we see multiple "keydown" events,
|
|
@@ -30659,6 +30654,11 @@ function useDraggable(args) {
|
|
|
30659
30654
|
if (type === "keyup") {
|
|
30660
30655
|
return;
|
|
30661
30656
|
}
|
|
30657
|
+
if (typeof constrainKeyboardMovement === "object") {
|
|
30658
|
+
const destination = constrainKeyboardMovement[directionForKey[event.key]];
|
|
30659
|
+
onMove(destination ?? point);
|
|
30660
|
+
return;
|
|
30661
|
+
}
|
|
30662
30662
|
const {
|
|
30663
30663
|
direction: yDownDirection,
|
|
30664
30664
|
altKey,
|
|
@@ -30679,7 +30679,7 @@ function useDraggable(args) {
|
|
|
30679
30679
|
for (const dx of tests) {
|
|
30680
30680
|
// Transform the test back into the point's coordinate system
|
|
30681
30681
|
const testMovement = mafs.vec.scale(direction, dx);
|
|
30682
|
-
const testPoint =
|
|
30682
|
+
const testPoint = constrainKeyboardMovement(mafs.vec.transform(mafs.vec.add(mafs.vec.transform(point, userTransform), testMovement), inverseTransform));
|
|
30683
30683
|
if (mafs.vec.dist(testPoint, point) > min) {
|
|
30684
30684
|
onMove(testPoint);
|
|
30685
30685
|
break;
|
|
@@ -30699,7 +30699,7 @@ function useDraggable(args) {
|
|
|
30699
30699
|
return;
|
|
30700
30700
|
}
|
|
30701
30701
|
const movement = mafs.vec.transform(pixelMovement, inverseViewTransform);
|
|
30702
|
-
onMove(
|
|
30702
|
+
onMove(mafs.vec.transform(mafs.vec.add(pickup.current, movement), inverseTransform));
|
|
30703
30703
|
}
|
|
30704
30704
|
}, {
|
|
30705
30705
|
target,
|
|
@@ -30711,6 +30711,12 @@ function useDraggable(args) {
|
|
|
30711
30711
|
dragging
|
|
30712
30712
|
};
|
|
30713
30713
|
}
|
|
30714
|
+
const directionForKey = {
|
|
30715
|
+
ArrowLeft: "left",
|
|
30716
|
+
ArrowRight: "right",
|
|
30717
|
+
ArrowUp: "up",
|
|
30718
|
+
ArrowDown: "down"
|
|
30719
|
+
};
|
|
30714
30720
|
function getInverseTransform(transform) {
|
|
30715
30721
|
const invert = mafs.vec.matrixInvert(transform);
|
|
30716
30722
|
invariant(invert !== null, "Could not invert transform matrix. A parent transformation matrix might be degenerative (mapping 2D space to a line).");
|
|
@@ -30760,7 +30766,7 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
30760
30766
|
range,
|
|
30761
30767
|
markings,
|
|
30762
30768
|
showTooltips,
|
|
30763
|
-
|
|
30769
|
+
disableKeyboardInteraction
|
|
30764
30770
|
} = useGraphConfig();
|
|
30765
30771
|
const {
|
|
30766
30772
|
point,
|
|
@@ -30805,7 +30811,7 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
30805
30811
|
cursor
|
|
30806
30812
|
},
|
|
30807
30813
|
"data-testid": "movable-point",
|
|
30808
|
-
tabIndex:
|
|
30814
|
+
tabIndex: disableKeyboardInteraction ? -1 : tabIndex(focusBehavior)
|
|
30809
30815
|
}, /*#__PURE__*/React__namespace.createElement("circle", {
|
|
30810
30816
|
className: "movable-point-hitbox",
|
|
30811
30817
|
r: hitboxSizePx / 2,
|
|
@@ -30894,7 +30900,7 @@ const MovableLine = props => {
|
|
|
30894
30900
|
function useControlPoint(point, color, onMovePoint) {
|
|
30895
30901
|
const {
|
|
30896
30902
|
snapStep,
|
|
30897
|
-
|
|
30903
|
+
disableKeyboardInteraction
|
|
30898
30904
|
} = useGraphConfig();
|
|
30899
30905
|
const [focused, setFocused] = React.useState(false);
|
|
30900
30906
|
const keyboardHandleRef = React.useRef(null);
|
|
@@ -30902,7 +30908,7 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
30902
30908
|
gestureTarget: keyboardHandleRef,
|
|
30903
30909
|
point,
|
|
30904
30910
|
onMove: onMovePoint,
|
|
30905
|
-
|
|
30911
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30906
30912
|
});
|
|
30907
30913
|
const visiblePointRef = React.useRef(null);
|
|
30908
30914
|
const {
|
|
@@ -30911,12 +30917,12 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
30911
30917
|
gestureTarget: visiblePointRef,
|
|
30912
30918
|
point,
|
|
30913
30919
|
onMove: onMovePoint,
|
|
30914
|
-
|
|
30920
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30915
30921
|
});
|
|
30916
30922
|
const focusableHandle = /*#__PURE__*/React__namespace.createElement("g", {
|
|
30917
30923
|
"data-testid": "movable-point__focusable-handle",
|
|
30918
30924
|
className: "movable-point__focusable-handle",
|
|
30919
|
-
tabIndex:
|
|
30925
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
30920
30926
|
ref: keyboardHandleRef,
|
|
30921
30927
|
onFocus: () => setFocused(true),
|
|
30922
30928
|
onBlur: () => setFocused(false)
|
|
@@ -30950,7 +30956,7 @@ const Line$1 = props => {
|
|
|
30950
30956
|
range,
|
|
30951
30957
|
graphDimensionsInPixels,
|
|
30952
30958
|
snapStep,
|
|
30953
|
-
|
|
30959
|
+
disableKeyboardInteraction
|
|
30954
30960
|
} = useGraphConfig();
|
|
30955
30961
|
let startExtend = undefined;
|
|
30956
30962
|
let endExtend = undefined;
|
|
@@ -30968,11 +30974,11 @@ const Line$1 = props => {
|
|
|
30968
30974
|
onMove: newPoint => {
|
|
30969
30975
|
onMove(mafs.vec.sub(newPoint, start));
|
|
30970
30976
|
},
|
|
30971
|
-
|
|
30977
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
30972
30978
|
});
|
|
30973
30979
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("g", {
|
|
30974
30980
|
ref: line,
|
|
30975
|
-
tabIndex:
|
|
30981
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
30976
30982
|
className: "movable-line",
|
|
30977
30983
|
"data-testid": "movable-line",
|
|
30978
30984
|
style: {
|
|
@@ -31443,7 +31449,7 @@ function calculateBisectorPoint(point1, point2, vertex, isReflex, allowReflex, a
|
|
|
31443
31449
|
return scaledBisector;
|
|
31444
31450
|
}
|
|
31445
31451
|
|
|
31446
|
-
const
|
|
31452
|
+
const MovablePoint$1 = props => {
|
|
31447
31453
|
const {
|
|
31448
31454
|
snapStep
|
|
31449
31455
|
} = useGraphConfig();
|
|
@@ -31453,16 +31459,15 @@ const StyledMovablePoint = props => {
|
|
|
31453
31459
|
onMove,
|
|
31454
31460
|
cursor,
|
|
31455
31461
|
color = wonderBlocksTokens.color.blue,
|
|
31456
|
-
|
|
31462
|
+
constrain = p => snap(snapStep, p)
|
|
31457
31463
|
} = props;
|
|
31458
|
-
const snapToValue = snapTo ?? "grid";
|
|
31459
31464
|
const {
|
|
31460
31465
|
dragging
|
|
31461
31466
|
} = useDraggable({
|
|
31462
31467
|
gestureTarget: elementRef,
|
|
31463
31468
|
point,
|
|
31464
31469
|
onMove,
|
|
31465
|
-
|
|
31470
|
+
constrainKeyboardMovement: constrain
|
|
31466
31471
|
});
|
|
31467
31472
|
return /*#__PURE__*/React__namespace.createElement(MovablePointView, {
|
|
31468
31473
|
ref: elementRef,
|
|
@@ -31478,8 +31483,10 @@ const StyledMovablePoint = props => {
|
|
|
31478
31483
|
};
|
|
31479
31484
|
|
|
31480
31485
|
const PolygonGraph = props => {
|
|
31481
|
-
const [focused, setFocused] = React__namespace.useState(false);
|
|
31482
31486
|
const [hovered, setHovered] = React__namespace.useState(false);
|
|
31487
|
+
// This is more so required for the re-rendering that occurs when state
|
|
31488
|
+
// updates; specifically with regard to line weighting and polygon focus.
|
|
31489
|
+
const [focusVisible, setFocusVisible] = React__namespace.useState(false);
|
|
31483
31490
|
const {
|
|
31484
31491
|
dispatch
|
|
31485
31492
|
} = props;
|
|
@@ -31489,10 +31496,10 @@ const PolygonGraph = props => {
|
|
|
31489
31496
|
showSides,
|
|
31490
31497
|
range,
|
|
31491
31498
|
snapStep,
|
|
31492
|
-
snapTo
|
|
31499
|
+
snapTo = "grid"
|
|
31493
31500
|
} = props.graphState;
|
|
31494
31501
|
const {
|
|
31495
|
-
|
|
31502
|
+
disableKeyboardInteraction
|
|
31496
31503
|
} = useGraphConfig();
|
|
31497
31504
|
|
|
31498
31505
|
// TODO(benchristel): can the default set of points be removed here? I don't
|
|
@@ -31500,7 +31507,7 @@ const PolygonGraph = props => {
|
|
|
31500
31507
|
const points = coords ?? [[0, 0]];
|
|
31501
31508
|
const ref = React__namespace.useRef(null);
|
|
31502
31509
|
const dragReferencePoint = points[0];
|
|
31503
|
-
const
|
|
31510
|
+
const constrain = ["angles", "sides"].includes(snapTo) ? p => p : p => snap(snapStep, p);
|
|
31504
31511
|
const {
|
|
31505
31512
|
dragging
|
|
31506
31513
|
} = useDraggable({
|
|
@@ -31510,16 +31517,15 @@ const PolygonGraph = props => {
|
|
|
31510
31517
|
const delta = mafs.vec.sub(newPoint, dragReferencePoint);
|
|
31511
31518
|
dispatch(actions.polygon.moveAll(delta));
|
|
31512
31519
|
},
|
|
31513
|
-
|
|
31520
|
+
constrainKeyboardMovement: constrain
|
|
31514
31521
|
});
|
|
31515
|
-
const active = hovered || focused || dragging;
|
|
31516
31522
|
const lastMoveTime = React__namespace.useRef(0);
|
|
31517
31523
|
const lines = getLines(points);
|
|
31518
31524
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Polygon, {
|
|
31519
31525
|
points: [...points],
|
|
31520
31526
|
color: "var(--movable-line-stroke-color)",
|
|
31521
31527
|
svgPolygonProps: {
|
|
31522
|
-
strokeWidth:
|
|
31528
|
+
strokeWidth: focusVisible ? "var(--movable-line-stroke-weight-active)" : "var(--movable-line-stroke-weight)",
|
|
31523
31529
|
style: {
|
|
31524
31530
|
fill: "transparent"
|
|
31525
31531
|
}
|
|
@@ -31534,11 +31540,10 @@ const PolygonGraph = props => {
|
|
|
31534
31540
|
key: "angle-" + i,
|
|
31535
31541
|
centerPoint: point,
|
|
31536
31542
|
endPoints: [pt1, pt2],
|
|
31537
|
-
active: active,
|
|
31538
31543
|
range: range,
|
|
31539
31544
|
polygonLines: lines,
|
|
31540
31545
|
showAngles: !!showAngles,
|
|
31541
|
-
snapTo:
|
|
31546
|
+
snapTo: snapTo
|
|
31542
31547
|
});
|
|
31543
31548
|
}), showSides && lines.map((_ref, i) => {
|
|
31544
31549
|
let [start, end] = _ref;
|
|
@@ -31554,21 +31559,29 @@ const PolygonGraph = props => {
|
|
|
31554
31559
|
color: "transparent",
|
|
31555
31560
|
svgPolygonProps: {
|
|
31556
31561
|
ref,
|
|
31557
|
-
tabIndex:
|
|
31562
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
31558
31563
|
strokeWidth: TARGET_SIZE,
|
|
31559
31564
|
style: {
|
|
31560
31565
|
cursor: dragging ? "grabbing" : "grab",
|
|
31561
31566
|
fill: hovered ? "var(--mafs-blue)" : "transparent"
|
|
31562
31567
|
},
|
|
31563
|
-
onFocus: () => setFocused(true),
|
|
31564
|
-
onBlur: () => setFocused(false),
|
|
31565
31568
|
onMouseEnter: () => setHovered(true),
|
|
31566
31569
|
onMouseLeave: () => setHovered(false),
|
|
31570
|
+
// Required to remove line weighting when user clicks away
|
|
31571
|
+
// from the focused polygon
|
|
31572
|
+
onKeyDownCapture: () => {
|
|
31573
|
+
setFocusVisible(hasFocusVisible(ref.current));
|
|
31574
|
+
},
|
|
31575
|
+
// Required for lines to darken on focus
|
|
31576
|
+
onFocus: () => setFocusVisible(hasFocusVisible(ref.current)),
|
|
31577
|
+
// Required for line weighting to update on blur. Without this,
|
|
31578
|
+
// the user has to hover over the shape for it to update
|
|
31579
|
+
onBlur: () => setFocusVisible(hasFocusVisible(ref.current)),
|
|
31567
31580
|
className: "movable-polygon"
|
|
31568
31581
|
}
|
|
31569
|
-
}), points.map((point, i) => /*#__PURE__*/React__namespace.createElement(
|
|
31582
|
+
}), points.map((point, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31570
31583
|
key: "point-" + i,
|
|
31571
|
-
|
|
31584
|
+
constrain: constrain,
|
|
31572
31585
|
point: point,
|
|
31573
31586
|
onMove: destination => {
|
|
31574
31587
|
const now = Date.now();
|
|
@@ -31587,6 +31600,17 @@ function getLines(points) {
|
|
|
31587
31600
|
return [point, next];
|
|
31588
31601
|
});
|
|
31589
31602
|
}
|
|
31603
|
+
const hasFocusVisible = element => {
|
|
31604
|
+
const matches = selector => element?.matches(selector) ?? false;
|
|
31605
|
+
try {
|
|
31606
|
+
return matches(":focus-visible");
|
|
31607
|
+
} catch (e) {
|
|
31608
|
+
// jsdom doesn't support :focus-visible
|
|
31609
|
+
// (see https://github.com/jsdom/jsdom/issues/3426),
|
|
31610
|
+
// so the call to matches(":focus-visible") will fail in tests.
|
|
31611
|
+
return matches(":focus");
|
|
31612
|
+
}
|
|
31613
|
+
};
|
|
31590
31614
|
|
|
31591
31615
|
function getGradableGraph(state, initialGraph) {
|
|
31592
31616
|
if (!state.hasBeenInteractedWith) {
|
|
@@ -31692,7 +31716,7 @@ function CircleGraph(props) {
|
|
|
31692
31716
|
center: center,
|
|
31693
31717
|
radius: getRadius(graphState),
|
|
31694
31718
|
onMove: c => dispatch(actions.circle.moveCenter(c))
|
|
31695
|
-
}), /*#__PURE__*/React__namespace.createElement(
|
|
31719
|
+
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31696
31720
|
point: radiusPoint,
|
|
31697
31721
|
cursor: "ew-resize",
|
|
31698
31722
|
onMove: newRadiusPoint => {
|
|
@@ -31708,7 +31732,7 @@ function MovableCircle(props) {
|
|
|
31708
31732
|
} = props;
|
|
31709
31733
|
const {
|
|
31710
31734
|
snapStep,
|
|
31711
|
-
|
|
31735
|
+
disableKeyboardInteraction
|
|
31712
31736
|
} = useGraphConfig();
|
|
31713
31737
|
const draggableRef = React.useRef(null);
|
|
31714
31738
|
const {
|
|
@@ -31717,13 +31741,13 @@ function MovableCircle(props) {
|
|
|
31717
31741
|
gestureTarget: draggableRef,
|
|
31718
31742
|
point: center,
|
|
31719
31743
|
onMove,
|
|
31720
|
-
|
|
31744
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
31721
31745
|
});
|
|
31722
31746
|
const [centerPx] = useTransformVectorsToPixels(center);
|
|
31723
31747
|
const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
|
|
31724
31748
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
31725
31749
|
ref: draggableRef,
|
|
31726
|
-
tabIndex:
|
|
31750
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
31727
31751
|
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
|
|
31728
31752
|
}, /*#__PURE__*/React__namespace.createElement("ellipse", {
|
|
31729
31753
|
className: "focus-ring",
|
|
@@ -31804,7 +31828,7 @@ function QuadraticGraph(props) {
|
|
|
31804
31828
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Plot.OfX, {
|
|
31805
31829
|
y: y,
|
|
31806
31830
|
color: wonderBlocksTokens.color.blue
|
|
31807
|
-
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(
|
|
31831
|
+
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31808
31832
|
key: "point-" + i,
|
|
31809
31833
|
point: coord,
|
|
31810
31834
|
onMove: destination => dispatch(actions.quadratic.movePoint(i, destination))
|
|
@@ -31864,7 +31888,7 @@ function SinusoidGraph(props) {
|
|
|
31864
31888
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Plot.OfX, {
|
|
31865
31889
|
y: x => computeSine(x, coeffRef.current),
|
|
31866
31890
|
color: wonderBlocksTokens.color.blue
|
|
31867
|
-
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(
|
|
31891
|
+
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31868
31892
|
key: "point-" + i,
|
|
31869
31893
|
point: coord,
|
|
31870
31894
|
onMove: destination => dispatch(actions.sinusoid.movePoint(i, destination))
|
|
@@ -31920,7 +31944,6 @@ function AngleGraph(props) {
|
|
|
31920
31944
|
showAngles,
|
|
31921
31945
|
range,
|
|
31922
31946
|
allowReflexAngles,
|
|
31923
|
-
angleOffsetDeg,
|
|
31924
31947
|
snapDegrees
|
|
31925
31948
|
} = graphState;
|
|
31926
31949
|
|
|
@@ -31959,8 +31982,6 @@ function AngleGraph(props) {
|
|
|
31959
31982
|
coords: endPoints,
|
|
31960
31983
|
allowReflexAngles: allowReflexAngles || false,
|
|
31961
31984
|
// Whether to allow reflex angles or not
|
|
31962
|
-
angleOffsetDeg: angleOffsetDeg || 0,
|
|
31963
|
-
// The angle offset from the x-axis
|
|
31964
31985
|
snapDegrees: snapDegrees || 1,
|
|
31965
31986
|
// The multiple of degrees to snap to
|
|
31966
31987
|
range: range,
|
|
@@ -31968,19 +31989,65 @@ function AngleGraph(props) {
|
|
|
31968
31989
|
};
|
|
31969
31990
|
|
|
31970
31991
|
// Render the lines, angle, and then movable points
|
|
31971
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, svgLines, /*#__PURE__*/React__namespace.createElement(Angle, angleParams),
|
|
31972
|
-
|
|
31973
|
-
|
|
31974
|
-
|
|
31975
|
-
|
|
31976
|
-
|
|
31992
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, svgLines, /*#__PURE__*/React__namespace.createElement(Angle, angleParams), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31993
|
+
point: coords[1],
|
|
31994
|
+
constrain: p => p,
|
|
31995
|
+
onMove: destination => dispatch(actions.angle.movePoint(1, destination))
|
|
31996
|
+
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31997
|
+
point: coords[0],
|
|
31998
|
+
constrain: getAngleSideConstraint(coords[0], coords[1], snapDegrees || 1),
|
|
31999
|
+
onMove: destination => dispatch(actions.angle.movePoint(0, destination))
|
|
32000
|
+
}), /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
32001
|
+
point: coords[2],
|
|
32002
|
+
constrain: getAngleSideConstraint(coords[2], coords[1], snapDegrees || 1),
|
|
32003
|
+
onMove: destination => dispatch(actions.angle.movePoint(2, destination))
|
|
32004
|
+
}));
|
|
32005
|
+
}
|
|
32006
|
+
const positiveX = [1, 0];
|
|
32007
|
+
const negativeX = [-1, 0];
|
|
32008
|
+
const positiveY = [0, 1];
|
|
32009
|
+
const negativeY = [0, -1];
|
|
32010
|
+
function getAngleSideConstraint(sidePoint, vertex, snapDegrees) {
|
|
32011
|
+
const currentAngle = calculateAngleInDegrees(mafs.vec.sub(sidePoint, vertex));
|
|
32012
|
+
|
|
32013
|
+
// Find the rays that start at the current point and point up, down, left
|
|
32014
|
+
// and right.
|
|
32015
|
+
const leftRay = [sidePoint, mafs.vec.add(sidePoint, negativeX)];
|
|
32016
|
+
const rightRay = [sidePoint, mafs.vec.add(sidePoint, positiveX)];
|
|
32017
|
+
const upRay = [sidePoint, mafs.vec.add(sidePoint, positiveY)];
|
|
32018
|
+
const downRay = [sidePoint, mafs.vec.add(sidePoint, negativeY)];
|
|
32019
|
+
|
|
32020
|
+
// find the angles that lie one snap step clockwise and counter-clockwise
|
|
32021
|
+
// from the current angle. These are the angles to which the side can be
|
|
32022
|
+
// moved.
|
|
32023
|
+
const oneStepCounterClockwise = currentAngle + snapDegrees;
|
|
32024
|
+
const oneStepClockwise = currentAngle - snapDegrees;
|
|
32025
|
+
|
|
32026
|
+
// find the rays that start from the vertex and point in the direction of
|
|
32027
|
+
// the angles we just computed.
|
|
32028
|
+
const counterClockwiseRay = [vertex, mafs.vec.add(vertex, polar(1, oneStepCounterClockwise))];
|
|
32029
|
+
const clockwiseRay = [vertex, mafs.vec.add(vertex, polar(1, oneStepClockwise))];
|
|
32030
|
+
|
|
32031
|
+
// find the intersections of those rays with the horizontal and vertical
|
|
32032
|
+
// rays extending from the sidePoint. These intersections are the points to
|
|
32033
|
+
// which sidePoint can move that will result in a rotation of `snapDegrees`.
|
|
32034
|
+
const left = findIntersectionOfRays(leftRay, counterClockwiseRay) ?? findIntersectionOfRays(leftRay, clockwiseRay);
|
|
32035
|
+
const right = findIntersectionOfRays(rightRay, counterClockwiseRay) ?? findIntersectionOfRays(rightRay, clockwiseRay);
|
|
32036
|
+
const up = findIntersectionOfRays(upRay, counterClockwiseRay) ?? findIntersectionOfRays(upRay, clockwiseRay);
|
|
32037
|
+
const down = findIntersectionOfRays(downRay, counterClockwiseRay) ?? findIntersectionOfRays(downRay, clockwiseRay);
|
|
32038
|
+
return {
|
|
32039
|
+
up: up ?? sidePoint,
|
|
32040
|
+
down: down ?? sidePoint,
|
|
32041
|
+
left: left ?? sidePoint,
|
|
32042
|
+
right: right ?? sidePoint
|
|
32043
|
+
};
|
|
31977
32044
|
}
|
|
31978
32045
|
|
|
31979
32046
|
function PointGraph(props) {
|
|
31980
32047
|
const {
|
|
31981
32048
|
dispatch
|
|
31982
32049
|
} = props;
|
|
31983
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, props.graphState.coords.map((point, i) => /*#__PURE__*/React__namespace.createElement(
|
|
32050
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, props.graphState.coords.map((point, i) => /*#__PURE__*/React__namespace.createElement(MovablePoint$1, {
|
|
31984
32051
|
key: i,
|
|
31985
32052
|
point: point,
|
|
31986
32053
|
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination))
|
|
@@ -32012,7 +32079,7 @@ function Protractor() {
|
|
|
32012
32079
|
gestureTarget: draggableRef,
|
|
32013
32080
|
onMove: setCenter,
|
|
32014
32081
|
point: center,
|
|
32015
|
-
|
|
32082
|
+
constrainKeyboardMovement: point => bound$1({
|
|
32016
32083
|
snapStep,
|
|
32017
32084
|
range,
|
|
32018
32085
|
point
|
|
@@ -32128,7 +32195,8 @@ const MafsGraph = props => {
|
|
|
32128
32195
|
state,
|
|
32129
32196
|
dispatch,
|
|
32130
32197
|
labels,
|
|
32131
|
-
hintMode
|
|
32198
|
+
hintMode,
|
|
32199
|
+
readOnly
|
|
32132
32200
|
} = props;
|
|
32133
32201
|
const [width, height] = props.box;
|
|
32134
32202
|
const tickStep = props.step;
|
|
@@ -32144,7 +32212,7 @@ const MafsGraph = props => {
|
|
|
32144
32212
|
width,
|
|
32145
32213
|
height,
|
|
32146
32214
|
labels,
|
|
32147
|
-
hintMode
|
|
32215
|
+
disableKeyboardInteraction: hintMode || readOnly
|
|
32148
32216
|
}
|
|
32149
32217
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
32150
32218
|
className: "mafs-graph",
|
|
@@ -32509,6 +32577,9 @@ const getAngleCoords = params => {
|
|
|
32509
32577
|
if (graph.coords) {
|
|
32510
32578
|
return graph.coords;
|
|
32511
32579
|
}
|
|
32580
|
+
if (graph.startCoords) {
|
|
32581
|
+
return graph.startCoords;
|
|
32582
|
+
}
|
|
32512
32583
|
const {
|
|
32513
32584
|
snapDegrees,
|
|
32514
32585
|
angleOffsetDeg
|
|
@@ -32538,6 +32609,7 @@ const getAngleCoords = params => {
|
|
|
32538
32609
|
return coords;
|
|
32539
32610
|
};
|
|
32540
32611
|
|
|
32612
|
+
const minDistanceBetweenAngleVertexAndSidePoint = 2;
|
|
32541
32613
|
function interactiveGraphReducer(state, action) {
|
|
32542
32614
|
switch (action.type) {
|
|
32543
32615
|
case REINITIALIZE:
|
|
@@ -32708,23 +32780,30 @@ function doMovePoint(state, action) {
|
|
|
32708
32780
|
case "angle":
|
|
32709
32781
|
// If the index is 1, we are moving the vertex of the angle,
|
|
32710
32782
|
// which will move the other two points as well
|
|
32711
|
-
|
|
32712
|
-
|
|
32783
|
+
const newState = (() => {
|
|
32784
|
+
if (action.index === 1) {
|
|
32785
|
+
const updatedCoords = boundAndSnapAngleVertex(state, action);
|
|
32786
|
+
return {
|
|
32787
|
+
...state,
|
|
32788
|
+
hasBeenInteractedWith: true,
|
|
32789
|
+
coords: updatedCoords
|
|
32790
|
+
};
|
|
32791
|
+
}
|
|
32713
32792
|
return {
|
|
32714
32793
|
...state,
|
|
32715
32794
|
hasBeenInteractedWith: true,
|
|
32716
|
-
coords:
|
|
32795
|
+
coords: setAtIndex({
|
|
32796
|
+
array: state.coords,
|
|
32797
|
+
index: action.index,
|
|
32798
|
+
newValue: boundAndSnapAngleEndPoints(action.destination, state, action.index)
|
|
32799
|
+
})
|
|
32717
32800
|
};
|
|
32801
|
+
})();
|
|
32802
|
+
if (angleSidePointsTooCloseToVertex(newState)) {
|
|
32803
|
+
// cancel the move
|
|
32804
|
+
return state;
|
|
32718
32805
|
}
|
|
32719
|
-
return
|
|
32720
|
-
...state,
|
|
32721
|
-
hasBeenInteractedWith: true,
|
|
32722
|
-
coords: setAtIndex({
|
|
32723
|
-
array: state.coords,
|
|
32724
|
-
index: action.index,
|
|
32725
|
-
newValue: boundAndSnapAngleEndPoints(action.destination, state, action.index)
|
|
32726
|
-
})
|
|
32727
|
-
};
|
|
32806
|
+
return newState;
|
|
32728
32807
|
case "polygon":
|
|
32729
32808
|
let newValue;
|
|
32730
32809
|
if (state.snapTo === "sides") {
|
|
@@ -32817,11 +32896,7 @@ function doMoveCenter(state, action) {
|
|
|
32817
32896
|
case "circle":
|
|
32818
32897
|
{
|
|
32819
32898
|
// Constrain the center of the circle to the chart range
|
|
32820
|
-
const constrainedCenter =
|
|
32821
|
-
snapStep: state.snapStep,
|
|
32822
|
-
range: state.range,
|
|
32823
|
-
point: action.destination
|
|
32824
|
-
});
|
|
32899
|
+
const constrainedCenter = boundAndSnapToGrid(action.destination, state);
|
|
32825
32900
|
|
|
32826
32901
|
// Reposition the radius point based on the new center
|
|
32827
32902
|
// (spread to make sure we're not going to mutate anything)
|
|
@@ -32856,10 +32931,10 @@ function doMoveRadiusPoint(state, action) {
|
|
|
32856
32931
|
case "circle":
|
|
32857
32932
|
{
|
|
32858
32933
|
const [xMin, xMax] = state.range[X];
|
|
32859
|
-
const nextRadiusPoint = [
|
|
32934
|
+
const nextRadiusPoint = snap(state.snapStep, [
|
|
32860
32935
|
// Constrain to graph range
|
|
32861
32936
|
// The +0 is to convert -0 to +0
|
|
32862
|
-
clamp(action.destination[X] + 0, xMin, xMax), state.center[1]];
|
|
32937
|
+
clamp(action.destination[X] + 0, xMin, xMax), state.center[1]]);
|
|
32863
32938
|
if (___default["default"].isEqual(nextRadiusPoint, state.center)) {
|
|
32864
32939
|
return state;
|
|
32865
32940
|
}
|
|
@@ -32949,17 +33024,16 @@ function boundAndSnapAngleVertex(_ref2, _ref3) {
|
|
|
32949
33024
|
|
|
32950
33025
|
// Get the current and upcoming positions of the vertex
|
|
32951
33026
|
const startingVertex = coordsCopy[1];
|
|
32952
|
-
|
|
32953
|
-
|
|
32954
|
-
|
|
32955
|
-
|
|
32956
|
-
|
|
33027
|
+
|
|
33028
|
+
// Prevent the vertex from getting too close to the edge, so that all
|
|
33029
|
+
// points of the angle can fit within the graph bounds.
|
|
33030
|
+
const insetAmount = mafs.vec.add(snapStep, [minDistanceBetweenAngleVertexAndSidePoint, minDistanceBetweenAngleVertexAndSidePoint]);
|
|
33031
|
+
const newVertex = clampToBox(inset(insetAmount, range), snap(snapStep, destination));
|
|
32957
33032
|
|
|
32958
33033
|
// Get the vector from the starting vertex to the new vertex
|
|
32959
33034
|
const delta = mafs.vec.add(newVertex, reverseVector(startingVertex));
|
|
32960
33035
|
|
|
32961
33036
|
// Apply the delta to each of the other two points so that the angle is maintained
|
|
32962
|
-
let valid = true;
|
|
32963
33037
|
const newPoints = {};
|
|
32964
33038
|
for (const i of [0, 2]) {
|
|
32965
33039
|
const oldPoint = coordsCopy[i];
|
|
@@ -32968,22 +33042,14 @@ function boundAndSnapAngleVertex(_ref2, _ref3) {
|
|
|
32968
33042
|
angle *= Math.PI / 180;
|
|
32969
33043
|
newPoint = constrainToBoundsOnAngle(newPoint, angle, range, snapStep);
|
|
32970
33044
|
newPoints[i] = newPoint;
|
|
32971
|
-
|
|
32972
|
-
// Check if the new point is too close to the vertex
|
|
32973
|
-
if (tooClose(newVertex, newPoint)) {
|
|
32974
|
-
valid = false;
|
|
32975
|
-
}
|
|
32976
33045
|
}
|
|
32977
33046
|
|
|
32978
33047
|
// Update the vertex after snapping to the snapStep
|
|
32979
33048
|
newPoints[1] = newVertex;
|
|
32980
|
-
|
|
32981
|
-
|
|
32982
|
-
|
|
32983
|
-
|
|
32984
|
-
coordsCopy[i] = newPoint;
|
|
32985
|
-
});
|
|
32986
|
-
}
|
|
33049
|
+
Object.entries(newPoints).forEach(_ref4 => {
|
|
33050
|
+
let [i, newPoint] = _ref4;
|
|
33051
|
+
coordsCopy[i] = newPoint;
|
|
33052
|
+
});
|
|
32987
33053
|
return coordsCopy;
|
|
32988
33054
|
}
|
|
32989
33055
|
|
|
@@ -33049,10 +33115,17 @@ function boundAndSnapAngleEndPoints(destinationPoint, _ref5, index) {
|
|
|
33049
33115
|
|
|
33050
33116
|
// Snap the angle to the nearest multiple of snapDegrees (if provided)
|
|
33051
33117
|
angle = Math.round((angle - offsetDegrees) / snap) * snap + offsetDegrees;
|
|
33052
|
-
|
|
33118
|
+
|
|
33119
|
+
// add 0.01 to prevent rounding errors from causing the point to snap to
|
|
33120
|
+
// a location that is too close to the vertex.
|
|
33121
|
+
const minDistance = minDistanceBetweenAngleVertexAndSidePoint + 0.01;
|
|
33122
|
+
const distance = Math.max(mafs.vec.dist(coordsCopy[index], vertex), minDistance);
|
|
33053
33123
|
const snappedValue = mafs.vec.add(vertex, polar(distance, angle));
|
|
33054
33124
|
return snappedValue;
|
|
33055
33125
|
}
|
|
33126
|
+
function angleSidePointsTooCloseToVertex(state) {
|
|
33127
|
+
return tooClose(state.coords[0], state.coords[1], state.range) || tooClose(state.coords[2], state.coords[1], state.range);
|
|
33128
|
+
}
|
|
33056
33129
|
function boundAndSnapToPolygonAngle(destinationPoint, _ref6, index) {
|
|
33057
33130
|
let {
|
|
33058
33131
|
range,
|
|
@@ -33283,7 +33356,12 @@ const StatefulMafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref)
|
|
|
33283
33356
|
React.useEffect(() => {
|
|
33284
33357
|
dispatch(changeRange([[xMinRange, xMaxRange], [yMinRange, yMaxRange]]));
|
|
33285
33358
|
}, [dispatch, xMinRange, xMaxRange, yMinRange, yMaxRange]);
|
|
33359
|
+
|
|
33360
|
+
// Update the graph whenever any of the following values changes.
|
|
33361
|
+
// This is necessary to keep the graph previews in sync with the updated
|
|
33362
|
+
// graph settings within the interative graph editor.
|
|
33286
33363
|
const numSegments = graph.type === "segment" ? graph.numSegments : null;
|
|
33364
|
+
const numPoints = graph.type === "point" ? graph.numPoints : null;
|
|
33287
33365
|
const numSides = graph.type === "polygon" ? graph.numSides : null;
|
|
33288
33366
|
const snapTo = graph.type === "polygon" ? graph.snapTo : null;
|
|
33289
33367
|
const showAngles = graph.type === "polygon" ? graph.showAngles : null;
|
|
@@ -33298,7 +33376,7 @@ const StatefulMafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref)
|
|
|
33298
33376
|
if (latestPropsRef.current !== originalPropsRef.current) {
|
|
33299
33377
|
dispatch(reinitialize(latestPropsRef.current));
|
|
33300
33378
|
}
|
|
33301
|
-
}, [graph.type, numSegments, numSides, snapTo, showAngles, showSides, latestPropsRef, graph.startCoords]);
|
|
33379
|
+
}, [graph.type, numPoints, numSegments, numSides, snapTo, showAngles, showSides, latestPropsRef, graph.startCoords]);
|
|
33302
33380
|
return /*#__PURE__*/React__namespace.createElement(MafsGraph, _extends({}, props, {
|
|
33303
33381
|
state: state,
|
|
33304
33382
|
dispatch: dispatch
|
|
@@ -34602,7 +34680,8 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
34602
34680
|
snapStep: snapStep,
|
|
34603
34681
|
box: box,
|
|
34604
34682
|
showTooltips: !!this.props.showTooltips,
|
|
34605
|
-
hintMode: this.props.hintMode
|
|
34683
|
+
hintMode: this.props.hintMode,
|
|
34684
|
+
readOnly: this.props.apiOptions?.readOnly
|
|
34606
34685
|
}));
|
|
34607
34686
|
}
|
|
34608
34687
|
return /*#__PURE__*/React__namespace.createElement(LegacyInteractiveGraph, _extends({
|
|
@@ -44524,7 +44603,7 @@ const init = function (options) {
|
|
|
44524
44603
|
|
|
44525
44604
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44526
44605
|
const libName = "@khanacademy/perseus";
|
|
44527
|
-
const libVersion = "
|
|
44606
|
+
const libVersion = "28.1.0";
|
|
44528
44607
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44529
44608
|
|
|
44530
44609
|
const apiVersion = {
|
|
@@ -45082,7 +45161,6 @@ const context = /*#__PURE__*/React__namespace.createContext(defaultContext);
|
|
|
45082
45161
|
const {
|
|
45083
45162
|
mapObject
|
|
45084
45163
|
} = objective_;
|
|
45085
|
-
/* eslint-disable-next-line react/no-unsafe */
|
|
45086
45164
|
class ServerItemRenderer extends React__namespace.Component {
|
|
45087
45165
|
static contextType = PerseusI18nContext;
|
|
45088
45166
|
// @ts-expect-error - TS2564 - Property 'questionRenderer' has no initializer and is not definitely assigned in the constructor.
|
|
@@ -46461,7 +46539,16 @@ class MultiRenderer extends React__namespace.Component {
|
|
|
46461
46539
|
// _annotateRendererArray() needs this
|
|
46462
46540
|
ref: null,
|
|
46463
46541
|
makeRenderer: () => /*#__PURE__*/React__namespace.createElement(HintsRenderer, _extends({}, this._getRendererProps(), {
|
|
46464
|
-
findExternalWidgets: findExternalWidgets
|
|
46542
|
+
findExternalWidgets: findExternalWidgets
|
|
46543
|
+
// Note(Jeremy): The MultiRenderer codebase types are
|
|
46544
|
+
// slightly different from the rest of the codebase.
|
|
46545
|
+
// Ideally `HintNode` would spread the `Hint` type into it,
|
|
46546
|
+
// but there is a difference in optionality of `widgets`
|
|
46547
|
+
// and `images` and that causes a huge cascade of type
|
|
46548
|
+
// errors (they are truly optional, but most of our code
|
|
46549
|
+
// assumes they're provided/set). Ignoring this for now.
|
|
46550
|
+
// @ts-expect-error - TS2769 - Type 'HintNode' is not assignable to type 'Hint'.
|
|
46551
|
+
,
|
|
46465
46552
|
hints: [hint]
|
|
46466
46553
|
}))
|
|
46467
46554
|
};
|
|
@@ -48178,12 +48265,15 @@ exports.generateTestNumericInputWidget = generateTestNumericInputWidget;
|
|
|
48178
48265
|
exports.generateTestPerseusItem = generateTestPerseusItem;
|
|
48179
48266
|
exports.generateTestRadioWidget = generateTestRadioWidget;
|
|
48180
48267
|
exports.genericPerseusItemData = genericPerseusItemData;
|
|
48268
|
+
exports.getAngleCoords = getAngleCoords;
|
|
48181
48269
|
exports.getAnswerFromUserInput = getAnswerFromUserInput;
|
|
48182
48270
|
exports.getAnswersFromWidgets = getAnswersFromWidgets;
|
|
48183
48271
|
exports.getCircleCoords = getCircleCoords;
|
|
48184
48272
|
exports.getCorrectAnswerForWidgetId = getCorrectAnswerForWidgetId;
|
|
48185
48273
|
exports.getLineCoords = getLineCoords;
|
|
48186
48274
|
exports.getLinearSystemCoords = getLinearSystemCoords;
|
|
48275
|
+
exports.getPointCoords = getPointCoords;
|
|
48276
|
+
exports.getPolygonCoords = getPolygonCoords;
|
|
48187
48277
|
exports.getQuadraticCoords = getQuadraticCoords;
|
|
48188
48278
|
exports.getSegmentCoords = getSegmentCoords;
|
|
48189
48279
|
exports.getSinusoidCoords = getSinusoidCoords;
|