@khanacademy/perseus 39.0.1 → 41.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/hud.d.ts +4 -0
- package/dist/components/i18n-context.d.ts +4 -0
- package/dist/components/icon.d.ts +28 -27
- package/dist/components/image-loader.d.ts +9 -9
- package/dist/components/inline-icon.d.ts +6 -9
- package/dist/components/lint.d.ts +13 -0
- package/dist/components/math-input.d.ts +2 -2
- package/dist/components/multi-button-group.d.ts +26 -0
- package/dist/components/number-input.d.ts +19 -0
- package/dist/components/range-input.d.ts +3 -0
- package/dist/components/stub-tag-editor.d.ts +2 -2
- package/dist/components/svg-image.d.ts +30 -0
- package/dist/components/tooltip.d.ts +41 -30
- package/dist/es/index.css +6 -0
- package/dist/es/index.js +1502 -2183
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +16 -2
- package/dist/es/strings.js.map +1 -1
- package/dist/icon-paths.d.ts +1 -65
- package/dist/index.css +6 -0
- package/dist/index.d.ts +11 -6
- package/dist/index.js +1509 -2175
- package/dist/index.js.map +1 -1
- package/dist/strings.d.ts +8 -0
- package/dist/strings.js +22 -2
- package/dist/strings.js.map +1 -1
- package/dist/styles/global-styles.d.ts +2 -47
- package/dist/types.d.ts +5 -5
- package/dist/widgets/expression/expression.d.ts +4 -4
- package/dist/widgets/grapher/util.d.ts +0 -4
- package/dist/widgets/interactive-graphs/graphs/angle.d.ts +2 -5
- package/dist/widgets/interactive-graphs/graphs/circle.d.ts +2 -5
- package/dist/widgets/interactive-graphs/graphs/components/movable-point-view.d.ts +1 -11
- package/dist/widgets/interactive-graphs/graphs/components/movable-point.d.ts +2 -1
- package/dist/widgets/interactive-graphs/graphs/components/use-control-point.d.ts +23 -0
- package/dist/widgets/interactive-graphs/graphs/linear-system.d.ts +2 -5
- package/dist/widgets/interactive-graphs/graphs/linear.d.ts +2 -5
- package/dist/widgets/interactive-graphs/graphs/point.d.ts +7 -5
- package/dist/widgets/interactive-graphs/graphs/polygon.d.ts +2 -5
- package/dist/widgets/interactive-graphs/graphs/quadratic.d.ts +2 -4
- package/dist/widgets/interactive-graphs/graphs/ray.d.ts +2 -5
- package/dist/widgets/interactive-graphs/graphs/screenreader-text.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/segment.d.ts +2 -5
- package/dist/widgets/interactive-graphs/graphs/sinusoid.d.ts +2 -5
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +1 -2
- package/dist/widgets/interactive-graphs/reducer/interactive-graph-action.d.ts +5 -0
- package/dist/widgets/interactive-graphs/types.d.ts +13 -1
- package/dist/widgets/interactive-graphs/utils.d.ts +3 -0
- package/dist/widgets/label-image/label-image.d.ts +2 -2
- package/package.json +10 -9
- package/dist/components/constants.d.ts +0 -7
- package/dist/styles/global-constants.d.ts +0 -342
- package/dist/widgets/interactive-graphs/graphs/index.d.ts +0 -9
package/dist/es/index.js
CHANGED
|
@@ -6,9 +6,9 @@ import { View, RenderStateRoot, UniqueIDProvider, useOnMountEffect, useLatestRef
|
|
|
6
6
|
import Tooltip$1 from '@khanacademy/wonder-blocks-tooltip';
|
|
7
7
|
import { HeadingMedium, LabelSmall, Body, LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
8
8
|
import { StyleSheet, css } from 'aphrodite';
|
|
9
|
-
import classNames from 'classnames';
|
|
9
|
+
import classNames$1 from 'classnames';
|
|
10
10
|
import * as React from 'react';
|
|
11
|
-
import React__default, { useContext, useState, useEffect, useRef, createContext, forwardRef, useImperativeHandle } from 'react';
|
|
11
|
+
import React__default, { useContext, useState, useEffect, useRef, createContext, forwardRef, useLayoutEffect, useImperativeHandle } from 'react';
|
|
12
12
|
import * as ReactDOM from 'react-dom';
|
|
13
13
|
import ReactDOM__default from 'react-dom';
|
|
14
14
|
import _, { debounce as debounce$1 } from 'underscore';
|
|
@@ -32,7 +32,7 @@ import { OptionItem, SingleSelect, MultiSelect } from '@khanacademy/wonder-block
|
|
|
32
32
|
import caretDown from '@phosphor-icons/core/regular/caret-down.svg';
|
|
33
33
|
import caretUp from '@phosphor-icons/core/regular/caret-up.svg';
|
|
34
34
|
import debounce$2 from 'lodash.debounce';
|
|
35
|
-
import { vec, Coordinates, Ellipse, Plot as Plot$3, Line as Line$4, Point as Point$2, Polygon,
|
|
35
|
+
import { vec, Coordinates, Ellipse, Plot as Plot$3, Line as Line$4, Point as Point$2, Polygon, Text as Text$1, useTransformContext, Mafs } from 'mafs';
|
|
36
36
|
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
37
37
|
import questionIcon from '@phosphor-icons/core/regular/question.svg';
|
|
38
38
|
import { useDrag } from '@use-gesture/react';
|
|
@@ -238,7 +238,15 @@ const mockStrings = {
|
|
|
238
238
|
simulationLocaleWarning: "Sorry, this simulation isn't available in your language.",
|
|
239
239
|
addPoint: "Add Point",
|
|
240
240
|
removePoint: "Remove Point",
|
|
241
|
-
graphKeyboardPrompt: "Press Shift + Enter to interact with the graph"
|
|
241
|
+
graphKeyboardPrompt: "Press Shift + Enter to interact with the graph",
|
|
242
|
+
srPointAtCoordinates: ({
|
|
243
|
+
x,
|
|
244
|
+
y
|
|
245
|
+
}) => `Point at ${x} comma ${y}`,
|
|
246
|
+
srInteractiveElements: ({
|
|
247
|
+
elements
|
|
248
|
+
}) => `Interactive elements: ${elements}`,
|
|
249
|
+
srNoInteractiveElements: "No interactive elements"
|
|
242
250
|
};
|
|
243
251
|
|
|
244
252
|
/**
|
|
@@ -246,11 +254,13 @@ const mockStrings = {
|
|
|
246
254
|
* used inside the Perseus package.
|
|
247
255
|
*
|
|
248
256
|
*/
|
|
249
|
-
|
|
250
|
-
const PerseusI18nContext = /*#__PURE__*/React.createContext(process.env.NODE_ENV === "test" || process.env.STORYBOOK ? {
|
|
257
|
+
const mockPerseusI18nContext = {
|
|
251
258
|
strings: mockStrings,
|
|
252
259
|
locale: "en"
|
|
253
|
-
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// @ts-expect-error - TS2322 - Type 'Context<{ strings: {}; locale: string; }>' is not assignable to type 'Context<I18nContextType>'.
|
|
263
|
+
const PerseusI18nContext = /*#__PURE__*/React.createContext(process.env.NODE_ENV === "test" || process.env.STORYBOOK ? mockPerseusI18nContext :
|
|
254
264
|
// We want to return null here, not an empty object, so that we
|
|
255
265
|
// are will throw an error when attempting to access the
|
|
256
266
|
// undefined locale or strings, making it easier to debug.
|
|
@@ -479,7 +489,7 @@ class InnerMathInput extends React.Component {
|
|
|
479
489
|
});
|
|
480
490
|
}
|
|
481
491
|
render() {
|
|
482
|
-
let className = classNames({
|
|
492
|
+
let className = classNames$1({
|
|
483
493
|
"perseus-math-input": true,
|
|
484
494
|
// mathquill usually adds these itself but react removes them when
|
|
485
495
|
// updating the component.
|
|
@@ -531,7 +541,7 @@ class InnerMathInput extends React.Component {
|
|
|
531
541
|
closeButtonVisible: true,
|
|
532
542
|
style: styles$E.popoverContent
|
|
533
543
|
}, /*#__PURE__*/React.createElement(DesktopKeypad, _extends({
|
|
534
|
-
onAnalyticsEvent: this.props.
|
|
544
|
+
onAnalyticsEvent: this.props.onAnalyticsEvent,
|
|
535
545
|
extraKeys: this.props.extraKeys,
|
|
536
546
|
onClickKey: this.handleKeypadPress,
|
|
537
547
|
cursorContext: this.state.cursorContext,
|
|
@@ -705,6 +715,9 @@ const getDependencies = () => {
|
|
|
705
715
|
const DependenciesContext = /*#__PURE__*/React.createContext({
|
|
706
716
|
analytics: {
|
|
707
717
|
onAnalyticsEvent: async () => {}
|
|
718
|
+
},
|
|
719
|
+
useVideo: () => {
|
|
720
|
+
throw new Error("useVideo dependency not provided in Perseus dependencies");
|
|
708
721
|
}
|
|
709
722
|
});
|
|
710
723
|
|
|
@@ -958,7 +971,7 @@ class TextListEditor extends React.Component {
|
|
|
958
971
|
}
|
|
959
972
|
TextListEditor.propTypes = {
|
|
960
973
|
options: PropTypes.array,
|
|
961
|
-
layout: PropTypes.
|
|
974
|
+
layout: PropTypes.oneOf(["horizontal", "vertical"]),
|
|
962
975
|
onChange: PropTypes.func.isRequired
|
|
963
976
|
};
|
|
964
977
|
TextListEditor.defaultProps = {
|
|
@@ -966,6 +979,8 @@ TextListEditor.defaultProps = {
|
|
|
966
979
|
layout: "horizontal"
|
|
967
980
|
};
|
|
968
981
|
|
|
982
|
+
const EMPTY_ARRAY = [];
|
|
983
|
+
|
|
969
984
|
/**
|
|
970
985
|
* Stub Tag Editor.
|
|
971
986
|
*
|
|
@@ -979,7 +994,6 @@ TextListEditor.defaultProps = {
|
|
|
979
994
|
* It also gives a nicer interface for the group metadata editor
|
|
980
995
|
* in local demo mode.
|
|
981
996
|
*/
|
|
982
|
-
const EMPTY_ARRAY = [];
|
|
983
997
|
class StubTagEditor extends React.Component {
|
|
984
998
|
render() {
|
|
985
999
|
return /*#__PURE__*/React.createElement("div", null, this.props.showTitle && /*#__PURE__*/React.createElement("div", {
|
|
@@ -2408,7 +2422,7 @@ class Expression extends React.Component {
|
|
|
2408
2422
|
}, cb);
|
|
2409
2423
|
}
|
|
2410
2424
|
render() {
|
|
2411
|
-
var _this$props$keypadCon, _this$props$analytics2;
|
|
2425
|
+
var _this$props$keypadCon, _this$props$analytics2, _this$props$analytics3;
|
|
2412
2426
|
if (this.props.apiOptions.customKeypad) {
|
|
2413
2427
|
return /*#__PURE__*/React.createElement(View, {
|
|
2414
2428
|
className: css(styles$D.mobileLabelInputWrapper)
|
|
@@ -2437,7 +2451,7 @@ class Expression extends React.Component {
|
|
|
2437
2451
|
onBlur: this._handleBlur
|
|
2438
2452
|
}));
|
|
2439
2453
|
}
|
|
2440
|
-
const className = classNames({
|
|
2454
|
+
const className = classNames$1({
|
|
2441
2455
|
"perseus-widget-expression": true,
|
|
2442
2456
|
"show-error-tooltip": this.state.showErrorTooltip
|
|
2443
2457
|
});
|
|
@@ -2481,9 +2495,7 @@ class Expression extends React.Component {
|
|
|
2481
2495
|
hasError: this.state.showErrorStyle,
|
|
2482
2496
|
ariaLabel: this.props.ariaLabel || this.context.strings.mathInputBox,
|
|
2483
2497
|
extraKeys: (_this$props$keypadCon = this.props.keypadConfiguration) == null ? void 0 : _this$props$keypadCon.extraKeys,
|
|
2484
|
-
|
|
2485
|
-
onAnalyticsEvent: async function () {}
|
|
2486
|
-
}
|
|
2498
|
+
onAnalyticsEvent: (_this$props$analytics2 = (_this$props$analytics3 = this.props.analytics) == null ? void 0 : _this$props$analytics3.onAnalyticsEvent) != null ? _this$props$analytics2 : async function () {}
|
|
2487
2499
|
}))));
|
|
2488
2500
|
}
|
|
2489
2501
|
}
|
|
@@ -3886,12 +3898,12 @@ Zoom.prototype.dispose = function () {
|
|
|
3886
3898
|
const ZoomService = new ZoomServiceClass();
|
|
3887
3899
|
|
|
3888
3900
|
// @baseFontFamily: "Lato", sans-serif;
|
|
3889
|
-
const baseFontFamily
|
|
3901
|
+
const baseFontFamily = "'Lato', sans-serif";
|
|
3890
3902
|
// @boldFontFamily: "Lato-Bold", "Lato", sans-serif;
|
|
3891
3903
|
const boldFontFamily = "'Lato-Bold', 'Lato', sans-serif";
|
|
3892
3904
|
// @kaGreen: #71b307;
|
|
3893
|
-
const kaGreen
|
|
3894
|
-
const white
|
|
3905
|
+
const kaGreen = "#71B307";
|
|
3906
|
+
const white = "#FFFFFF";
|
|
3895
3907
|
const gray97 = "#F6F7F7";
|
|
3896
3908
|
const gray85 = "#D6D8DA";
|
|
3897
3909
|
const gray76 = "#BABEC2";
|
|
@@ -3899,23 +3911,23 @@ const gray68 = "#888D93";
|
|
|
3899
3911
|
const gray17 = "#21242c";
|
|
3900
3912
|
|
|
3901
3913
|
// @pure-sm-min: 568px;
|
|
3902
|
-
const pureSmMin$
|
|
3914
|
+
const pureSmMin$1 = "568px";
|
|
3903
3915
|
// @pure-md-min: 768px;
|
|
3904
|
-
const pureMdMin$
|
|
3916
|
+
const pureMdMin$1 = "768px";
|
|
3905
3917
|
// @pure-lg-min: 1024px;
|
|
3906
|
-
const pureLgMin$
|
|
3918
|
+
const pureLgMin$1 = "1024px";
|
|
3907
3919
|
// @pure-xl-min: 1280px;
|
|
3908
|
-
const pureXlMin$
|
|
3920
|
+
const pureXlMin$1 = "1280px";
|
|
3909
3921
|
// @pure-xs-max: (@pure-sm-min - 1);
|
|
3910
|
-
const pureXsMax$
|
|
3922
|
+
const pureXsMax$1 = "567px";
|
|
3911
3923
|
// @pure-sm-max: (@pure-md-min - 1);
|
|
3912
|
-
const pureSmMax$
|
|
3924
|
+
const pureSmMax$1 = "767px";
|
|
3913
3925
|
// @pure-md-max: (@pure-lg-min - 1);
|
|
3914
|
-
const pureMdMax$
|
|
3926
|
+
const pureMdMax$1 = "1023px";
|
|
3915
3927
|
// @pure-lg-max: (@pure-xl-min - 1);
|
|
3916
|
-
const pureLgMax$
|
|
3928
|
+
const pureLgMax$1 = "1279px";
|
|
3917
3929
|
// @tableBackgroundAccent: #f9f9f9; // for striping
|
|
3918
|
-
const tableBackgroundAccent
|
|
3930
|
+
const tableBackgroundAccent = "#F9F9F9";
|
|
3919
3931
|
// @zIndexAboveScratchpad: @zIndexScratchPad + 1;
|
|
3920
3932
|
const zIndexAboveScratchpad$1 = 2;
|
|
3921
3933
|
// @zIndexInteractiveComponent: @zIndexAboveScratchpad + 1;
|
|
@@ -3943,26 +3955,26 @@ const checkedColor$1 = "#71B307";
|
|
|
3943
3955
|
const articleMaxWidthInPx = 688;
|
|
3944
3956
|
const articleMaxWidthTableInPx = 512;
|
|
3945
3957
|
|
|
3946
|
-
var constants
|
|
3958
|
+
var constants = /*#__PURE__*/Object.freeze({
|
|
3947
3959
|
__proto__: null,
|
|
3948
|
-
baseFontFamily: baseFontFamily
|
|
3960
|
+
baseFontFamily: baseFontFamily,
|
|
3949
3961
|
boldFontFamily: boldFontFamily,
|
|
3950
|
-
kaGreen: kaGreen
|
|
3951
|
-
white: white
|
|
3962
|
+
kaGreen: kaGreen,
|
|
3963
|
+
white: white,
|
|
3952
3964
|
gray97: gray97,
|
|
3953
3965
|
gray85: gray85,
|
|
3954
3966
|
gray76: gray76,
|
|
3955
3967
|
gray68: gray68,
|
|
3956
3968
|
gray17: gray17,
|
|
3957
|
-
pureSmMin: pureSmMin$
|
|
3958
|
-
pureMdMin: pureMdMin$
|
|
3959
|
-
pureLgMin: pureLgMin$
|
|
3960
|
-
pureXlMin: pureXlMin$
|
|
3961
|
-
pureXsMax: pureXsMax$
|
|
3962
|
-
pureSmMax: pureSmMax$
|
|
3963
|
-
pureMdMax: pureMdMax$
|
|
3964
|
-
pureLgMax: pureLgMax$
|
|
3965
|
-
tableBackgroundAccent: tableBackgroundAccent
|
|
3969
|
+
pureSmMin: pureSmMin$1,
|
|
3970
|
+
pureMdMin: pureMdMin$1,
|
|
3971
|
+
pureLgMin: pureLgMin$1,
|
|
3972
|
+
pureXlMin: pureXlMin$1,
|
|
3973
|
+
pureXsMax: pureXsMax$1,
|
|
3974
|
+
pureSmMax: pureSmMax$1,
|
|
3975
|
+
pureMdMax: pureMdMax$1,
|
|
3976
|
+
pureLgMax: pureLgMax$1,
|
|
3977
|
+
tableBackgroundAccent: tableBackgroundAccent,
|
|
3966
3978
|
zIndexAboveScratchpad: zIndexAboveScratchpad$1,
|
|
3967
3979
|
zIndexInteractiveComponent: zIndexInteractiveComponent$1,
|
|
3968
3980
|
phoneMargin: phoneMargin,
|
|
@@ -4080,7 +4092,7 @@ class FixedToResponsive extends React.Component {
|
|
|
4080
4092
|
};
|
|
4081
4093
|
|
|
4082
4094
|
// NOTE(jeremy): This depends on styles defined in perseus-renderer.less
|
|
4083
|
-
const className = classNames("fixed-to-responsive", this.props.className);
|
|
4095
|
+
const className = classNames$1("fixed-to-responsive", this.props.className);
|
|
4084
4096
|
const container = /*#__PURE__*/React.createElement("div", {
|
|
4085
4097
|
className: className,
|
|
4086
4098
|
style: style
|
|
@@ -14800,11 +14812,7 @@ _.extend(MovableLine$4.prototype, {
|
|
|
14800
14812
|
* A stripped version of Icon.jsx from webapp. Takes an SVG icon and renders it
|
|
14801
14813
|
* inline like Font Awesome did.
|
|
14802
14814
|
*
|
|
14803
|
-
*
|
|
14804
|
-
* webapp's `icon-paths.js` which is a reference file for all the SVG paths
|
|
14805
|
-
* that we've used. You'll need to copy the object from that file into
|
|
14806
|
-
* whichever file you're using the icon and explicitly pass it in to the
|
|
14807
|
-
* <InlineIcon/> React component.
|
|
14815
|
+
* You can refer to `icon-paths.ts` for all available SVG icons.
|
|
14808
14816
|
*
|
|
14809
14817
|
* We assume that the viewBox is cropped and aligned to (0, 0), but icons can
|
|
14810
14818
|
* be defined differently. At some point we might want to add these attributes
|
|
@@ -14812,13 +14820,14 @@ _.extend(MovableLine$4.prototype, {
|
|
|
14812
14820
|
*
|
|
14813
14821
|
* Sample usage:
|
|
14814
14822
|
*
|
|
14815
|
-
*
|
|
14823
|
+
* ```
|
|
14824
|
+
* const editIcon = {
|
|
14816
14825
|
* path: "M41.209 53.753l5.39 0l0 5.39l3.136 0l6.468-6.517-8.477-8.526-6.517 6.517l0 3.136zm33.173-34.937q-.882-.882-1.862.049l-19.6 19.6q-.931.98-.049 1.862t1.862-.049l19.6-19.6q.931-.98.049-1.862zm-38.563 45.668l0-16.121l37.632-37.632 16.17 16.121-37.632 37.632l-16.17 0zm43.022-12.397l0 10.633q-.049 6.713-4.753 11.417t-11.368 4.704l-46.599 0q-6.713 0-11.417-4.753t-4.704-11.368l0-46.599q0-6.664 4.753-11.417t11.368-4.704l46.599 0q3.528 0 6.566 1.372.833.392.98 1.323t-.49 1.617l-2.744 2.744q-.784.784-1.96.441t-2.352-.343l-46.599 0q-3.675 0-6.321 2.646t-2.646 6.321l0 46.599q0 3.675 2.646 6.321t6.321 2.646l46.599 0q3.675 0 6.321-2.646t2.646-6.321l0-7.056q0-.735.49-1.225l3.577-3.577q.833-.833 1.96-.392t1.127 1.617zm7.203-51.646q2.254 0 3.773 1.568l8.526 8.526q1.568 1.568 1.568 3.822t-1.568 3.773l-5.145 5.145-16.121-16.121 5.145-5.145q1.568-1.568 3.822-1.568z",
|
|
14817
14826
|
* width: 100,
|
|
14818
14827
|
* height: 78.912,
|
|
14819
|
-
*
|
|
14820
|
-
*
|
|
14821
|
-
*
|
|
14828
|
+
* };
|
|
14829
|
+
* <InlineIcon {...editIcon} />
|
|
14830
|
+
* ```
|
|
14822
14831
|
*/
|
|
14823
14832
|
const InlineIcon = ({
|
|
14824
14833
|
path,
|
|
@@ -14841,11 +14850,7 @@ const InlineIcon = ({
|
|
|
14841
14850
|
}));
|
|
14842
14851
|
|
|
14843
14852
|
/**
|
|
14844
|
-
* Icon paths to be used with `inline-icon.
|
|
14845
|
-
*
|
|
14846
|
-
* These paths are taken directly from webapp's `icon-paths.js`. Unlike the
|
|
14847
|
-
* webapp equivalent, these can be directly required within Perseus files since
|
|
14848
|
-
* this is all bundled together anyway.
|
|
14853
|
+
* Icon paths to be used with `inline-icon.tsx` and `icon.tsx`.
|
|
14849
14854
|
*/
|
|
14850
14855
|
|
|
14851
14856
|
const iconCheck = {
|
|
@@ -14853,77 +14858,26 @@ const iconCheck = {
|
|
|
14853
14858
|
width: 24,
|
|
14854
14859
|
height: 24
|
|
14855
14860
|
};
|
|
14856
|
-
const iconCheckMedium = {
|
|
14857
|
-
path: "M6.072 10.4l6.175-7.058a1 1 0 1 1 1.506 1.317L6.769 12.64a1 1 0 0 1-1.55-.054L2.203 8.604a1 1 0 1 1 1.594-1.208L6.072 10.4z",
|
|
14858
|
-
width: 16,
|
|
14859
|
-
height: 16
|
|
14860
|
-
};
|
|
14861
14861
|
const iconChevronDown = {
|
|
14862
14862
|
path: "M99.669 13.048q0 3.36-2.352 5.712l-41.664 41.664q-2.408 2.408-5.88 2.408t-5.712-2.408l-41.664-41.664q-2.408-2.24-2.408-5.712t2.408-5.88l4.76-4.816q2.52-2.352 5.88-2.352t5.656 2.352l31.136 31.136 31.08-31.136q2.352-2.352 5.712-2.352t5.88 2.352l4.816 4.816q2.352 2.52 2.352 5.88z",
|
|
14863
14863
|
width: 100,
|
|
14864
14864
|
height: 63.034
|
|
14865
14865
|
};
|
|
14866
|
-
const iconChevronRight = {
|
|
14867
|
-
path: "M62.808 49.728q0 3.36-2.352 5.88l-41.72 41.664q-2.352 2.408-5.768 2.408t-5.768-2.408l-4.872-4.76q-2.352-2.52-2.352-5.88t2.352-5.712l31.08-31.136-31.08-31.024q-2.352-2.52-2.352-5.88t2.352-5.712l4.872-4.76q2.296-2.408 5.768-2.408t5.768 2.408l41.72 41.664q2.352 2.296 2.352 5.656z",
|
|
14868
|
-
width: 63.034,
|
|
14869
|
-
height: 100
|
|
14870
|
-
};
|
|
14871
14866
|
const iconCircle = {
|
|
14872
14867
|
path: "M100.035 50.046q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",
|
|
14873
14868
|
width: 100,
|
|
14874
14869
|
height: 100
|
|
14875
14870
|
};
|
|
14876
|
-
const iconCircleArrowDown = {
|
|
14877
|
-
path: "M50.046 83.676q1.767 0 2.907-1.14l29.526-29.526q1.197-1.197 1.197-2.907t-1.197-2.964l-5.928-5.928q-1.197-1.14-2.964-1.14t-2.907 1.14l-12.312 12.312l0-32.661q0-1.71-1.254-2.964t-2.907-1.254l-8.322 0q-1.71 0-2.964 1.254t-1.254 2.964l0 32.661l-12.312-12.312q-1.197-1.254-2.907-1.254t-2.907 1.254l-5.928 5.928q-1.197 1.197-1.197 2.964t1.197 2.907l29.469 29.526q1.197 1.14 2.964 1.14zm49.989-33.63q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",
|
|
14878
|
-
width: 100,
|
|
14879
|
-
height: 100
|
|
14880
|
-
};
|
|
14881
|
-
const iconCircleArrowUp = {
|
|
14882
|
-
path: "M54.207 83.391q1.653 0 2.907-1.254t1.254-2.907l0-32.718l12.312 12.312q1.254 1.254 2.964 1.254t2.907-1.254l5.928-5.928q1.197-1.197 1.14-2.964 0-1.767-1.14-2.907l-29.526-29.526q-1.197-1.14-2.907-1.14t-2.964 1.14l-29.469 29.526q-1.197 1.254-1.197 2.964t1.197 2.907l5.928 5.928q1.197 1.197 2.907 1.197t2.907-1.197l12.312-12.312l0 32.718q0 1.653 1.254 2.907t2.964 1.254l8.322 0zm45.828-33.345q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",
|
|
14883
|
-
width: 100,
|
|
14884
|
-
height: 100
|
|
14885
|
-
};
|
|
14886
14871
|
const iconCircleThin = {
|
|
14887
14872
|
path: "M50.046 8.322q-8.493 0-16.188 3.306-15.561 6.669-22.173 22.23-3.363 7.695-3.363 16.188t3.306 16.188 8.949 13.281q5.586 5.586 13.281 8.892t16.188 3.306 16.188-3.306 13.281-8.892 8.892-13.281 3.306-16.188-3.306-16.188-8.892-13.281-13.281-8.949q-7.695-3.306-16.188-3.306zm0 91.713q-13.623 0-25.137-6.726t-18.183-18.183q-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.726 25.137-6.726 25.137-18.24 18.126q-11.514 6.726-25.08 6.726z",
|
|
14888
14873
|
width: 100,
|
|
14889
14874
|
height: 99.944
|
|
14890
14875
|
};
|
|
14891
|
-
const iconDesktop = {
|
|
14892
|
-
path: "M94.208 52.119l0-43.746q0-.69-.506-1.15t-1.196-.506l-84.088 0q-.69 0-1.196.506t-.506 1.15l0 43.746q0 .69.506 1.196t1.196.506l84.088 0q.69 0 1.196-.506t.506-1.196zm6.716-43.746l0 57.224q0 3.45-2.484 5.934t-5.934 2.484l-28.566 0q0 3.128 2.53 7.774.828 1.61.828 2.622t-1.012 2.07q-1.012 1.012-2.346.966l-26.91 0q-1.38 0-2.392-1.012t-1.012-2.024q0-1.058 1.656-4.14t1.748-6.256l-28.612 0q-3.45 0-5.934-2.484t-2.484-5.934l0-57.224q0-3.45 2.484-5.934t5.934-2.438l84.088 0q3.45 0 5.98 2.438 2.438 2.484 2.438 5.934z",
|
|
14893
|
-
width: 100,
|
|
14894
|
-
height: 86.648
|
|
14895
|
-
};
|
|
14896
|
-
const iconDropdownArrow = {
|
|
14897
|
-
path: "M9 9.8c0 .5.7 1.7 1.5 2.8 1.5 1.9 1.5 1.9 3 0C15.7 9.7 15.4 9 12 9c-1.6 0-3 .4-3 .8z",
|
|
14898
|
-
width: 24,
|
|
14899
|
-
height: 24
|
|
14900
|
-
};
|
|
14901
|
-
const iconExclamationSign = {
|
|
14902
|
-
path: "M58.368 81.225l0-12.369q0-.912-.57-1.539t-1.425-.627l-12.54 0q-.855-.057-1.482.627t-.684 1.539l0 12.369q-.057.855.627 1.482t1.539.684l12.54 0q.855 0 1.425-.627t.57-1.539zm1.026-62.871q0-1.596-2.223-1.71l-14.307 0q-2.109 0-2.223 1.71l1.14 40.47q0 .627.627 1.14t1.539.456l12.084 0q.912-.057 1.539-.513t.684-1.083zm-9.348-18.354q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.726 25.137-6.726 25.137-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669z",
|
|
14903
|
-
width: 100,
|
|
14904
|
-
height: 99.944
|
|
14905
|
-
};
|
|
14906
|
-
// Grabbed from https://github.com/encharm/Font-Awesome-SVG-PNG
|
|
14907
|
-
const iconGear = {
|
|
14908
|
-
path: "M1152 896q0-106-75-181t-181-75-181 75-75 181 75 181 181 75 181-75 75-181zm512-109v222q0 12-8 23t-20 13l-185 28q-19 54-39 91 35 50 107 138 10 12 10 25t-9 23q-27 37-99 108t-94 71q-12 0-26-9l-138-108q-44 23-91 38-16 136-29 186-7 28-36 28h-222q-14 0-24.5-8.5t-11.5-21.5l-28-184q-49-16-90-37l-141 107q-10 9-25 9-14 0-25-11-126-114-165-168-7-10-7-23 0-12 8-23 15-21 51-66.5t54-70.5q-27-50-41-99l-183-27q-13-2-21-12.5t-8-23.5v-222q0-12 8-23t19-13l186-28q14-46 39-92-40-57-107-138-10-12-10-24 0-10 9-23 26-36 98.5-107.5t94.5-71.5q13 0 26 10l138 107q44-23 91-38 16-136 29-186 7-28 36-28h222q14 0 24.5 8.5t11.5 21.5l28 184q49 16 90 37l142-107q9-9 24-9 13 0 25 10 129 119 165 170 7 8 7 22 0 12-8 23-15 21-51 66.5t-54 70.5q26 50 41 98l183 28q13 2 21 12.5t8 23.5z",
|
|
14909
|
-
width: 1792,
|
|
14910
|
-
height: 1792
|
|
14911
|
-
};
|
|
14912
|
-
const iconMobilePhone = {
|
|
14913
|
-
path: "M36.04 89.557q0-2.584-1.836-4.42t-4.42-1.836-4.352 1.836q-1.836 1.836-1.836 4.42t1.836 4.352 4.42 1.836q2.652-.068 4.42-1.836t1.768-4.352zm16.184-12.444l0-54.74q0-1.088-.748-1.768t-1.768-.68l-39.78 0q-1.088 0-1.768.748t-.68 1.7l0 54.74q0 1.02.748 1.768t1.7.68l39.78 0q1.02-.068 1.768-.748t.748-1.7zm-14.892-65.892q0-1.224-1.292-1.292l-12.444 0q-1.224.068-1.224 1.292t1.224 1.224l12.444 0q1.292 0 1.292-1.224zm22.372-1.292l0 79.628q0 3.944-2.992 6.936t-7.004 2.992l-39.78 0q-4.012 0-7.004-2.924-2.924-2.924-2.924-7.004l0-79.628q0-4.012 2.924-6.936t7.004-2.992l39.78 0q4.012-.068 7.004 2.924t2.992 7.004z",
|
|
14914
|
-
width: 60.013,
|
|
14915
|
-
height: 100
|
|
14916
|
-
};
|
|
14917
14876
|
const iconOk = {
|
|
14918
14877
|
path: "M37.964 76.048q-2.576 0-4.368-1.792l-31.864-31.864q-1.792-1.792-1.792-4.368t1.792-4.368l8.736-8.68q1.792-1.792 4.368-1.792t4.312 1.792l18.816 18.872 42-42.056q1.792-1.792 4.368-1.792t4.312 1.792l8.736 8.736q1.792 1.792 1.792 4.368t-1.792 4.312l-55.048 55.048q-1.792 1.792-4.368 1.792z",
|
|
14919
14878
|
width: 100,
|
|
14920
14879
|
height: 76.637
|
|
14921
14880
|
};
|
|
14922
|
-
const iconPlus = {
|
|
14923
|
-
path: "M99.758 43.09l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-29.45 0l0 29.45q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-29.45l-29.45 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l29.45 0l0-29.45q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836l0 29.45l29.45 0q2.852 0 4.836 1.984t1.984 4.836z",
|
|
14924
|
-
width: 100,
|
|
14925
|
-
height: 100
|
|
14926
|
-
};
|
|
14927
14881
|
const iconRemove = {
|
|
14928
14882
|
path: "M100.464 80.808q0 3.404-2.368 5.772l-11.47 11.544q-2.368 2.368-5.772 2.368t-5.698-2.368l-24.864-24.864-24.864 24.864q-2.368 2.368-5.772 2.368t-5.772-2.368l-11.47-11.544q-2.368-2.368-2.368-5.772t2.368-5.698l24.864-24.864-24.864-24.864q-2.368-2.368-2.368-5.772t2.368-5.772l11.47-11.47q2.368-2.368 5.772-2.368t5.772 2.368l24.864 24.864 24.864-24.864q2.294-2.368 5.698-2.368t5.772 2.368l11.47 11.47q2.368 2.368 2.368 5.772t-2.368 5.772l-24.864 24.864 24.864 24.864q2.368 2.294 2.368 5.698z",
|
|
14929
14883
|
width: 100,
|
|
@@ -14939,53 +14893,17 @@ const iconTryAgain = {
|
|
|
14939
14893
|
width: 23,
|
|
14940
14894
|
height: 23
|
|
14941
14895
|
};
|
|
14942
|
-
const iconTablet = {
|
|
14943
|
-
path: "M45.322 90.706q0-1.86-1.302-3.224-1.364-1.364-3.224-1.364t-3.224 1.364-1.302 3.224q0 1.86 1.364 3.224 1.302 1.364 3.162 1.302 1.86.062 3.224-1.302t1.302-3.224zm27.218-11.346l0-68.014q0-.93-.682-1.612t-1.55-.682l-58.962 0q-.93 0-1.612.682t-.682 1.612l0 68.014q0 .93.682 1.612t1.612.62l58.962 0q.992-.062 1.612-.682t.62-1.55zm9.114-68.014l0 77.066q0 4.65-3.348 7.998t-7.998 3.348l-58.962 0q-4.65 0-7.998-3.348t-3.348-7.998l0-77.066q0-4.65 3.348-7.998t7.998-3.348l58.962 0q4.65 0 7.998 3.348t3.348 7.998z",
|
|
14944
|
-
width: 81.852,
|
|
14945
|
-
height: 100
|
|
14946
|
-
};
|
|
14947
14896
|
const iconTrash = {
|
|
14948
14897
|
path: "M31.293 37.506q2.052 0 2.052 2.109l0 37.506q0 1.995-2.052 2.109l-4.218 0q-.912-.057-1.482-.627t-.57-1.482l0-37.506q0-2.109 2.052-2.109l4.218 0zm18.753 2.109l0 37.506q0 .912-.57 1.482t-1.539.627l-4.161 0q-1.995 0-2.109-2.109l0-37.506q.057-.912.627-1.482t1.482-.627l4.161 0q.969.057 1.539.627t.57 1.482zm14.592-2.109q2.052 0 2.052 2.109l0 37.506q0 1.995-2.052 2.109l-4.161 0q-.969-.057-1.539-.627t-.57-1.482l0-37.506q0-2.109 2.109-2.109l4.161 0zm10.431 49.248l0-61.731l-58.368 0l0 61.731q.057 2.679.969 3.819t1.083 1.14l54.207 0q.171 0 1.14-1.083t.969-3.876zm-43.776-70.11l29.184 0l-3.135-7.581q-.456-.57-1.14-.741l-20.634 0q-.627.114-1.083.741zm-31.293 2.109q0-1.995 2.109-2.109l20.121 0l4.56-10.83q.969-2.394 3.477-4.104 2.565-1.71 5.187-1.71l20.805 0q2.622 0 5.187 1.71t3.477 4.104l4.56 10.83l20.178 0q.912.057 1.482.627t.57 1.482l0 4.161q0 1.995-2.052 2.109l-6.27 0l0 61.731q0 5.415-3.078 9.348t-7.353 3.933l-54.207 0q-4.275 0-7.353-3.819t-3.078-9.177l0-62.016l-6.213 0q-.969 0-1.539-.57t-.57-1.539l0-4.161z",
|
|
14949
14898
|
width: 91.681,
|
|
14950
14899
|
height: 100
|
|
14951
14900
|
};
|
|
14952
|
-
const iconUndo = {
|
|
14953
|
-
path: "M10,6.6C10,7.2,9.8,8,9.3,9.1c0,0,0,0.1-0.1,0.1S9.2,9.3,9.2,9.4c0,0,0,0.1-0.1,0.1C9,9.6,9,9.6,8.9,9.6 c-0.1,0-0.1,0-0.1-0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1s0-0.1,0-0.1c0-0.3,0-0.5,0-0.7c0-0.4,0-0.7-0.1-1C8.6,7.1,8.5,6.9,8.4,6.7S8.2,6.3,8,6.1C7.8,5.9,7.6,5.8,7.4,5.7S6.9,5.5,6.7,5.5S6.1,5.4,5.8,5.4c-0.3,0-0.6,0-1,0H3.6v1.4c0,0.1,0,0.2-0.1,0.3C3.4,7.1,3.3,7.1,3.2,7.1C3.1,7.1,3,7.1,3,7L0.1,4.1C0,4.1,0,4,0,3.9s0-0.2,0.1-0.3L3,0.8C3,0.7,3.1,0.7,3.2,0.7c0.1,0,0.2,0,0.3,0.1C3.5,0.9,3.6,0.9,3.6,1v1.4h1.2c2.6,0,4.3,0.7,4.9,2.2C9.9,5.2,10,5.8,10,6.6z",
|
|
14954
|
-
width: 10,
|
|
14955
|
-
height: 10
|
|
14956
|
-
};
|
|
14957
14901
|
const iconMinus = {
|
|
14958
14902
|
path: `M8,13 L16,13 C16.5522847,13 17,12.5522847 17,12 C17,11.4477153 16.5522847,11 16,11 L8,11 C7.44771525,11 7,11.4477153 7,12 C7,12.5522847 7.44771525,13 8,13 Z`,
|
|
14959
14903
|
width: 24,
|
|
14960
14904
|
height: 24
|
|
14961
14905
|
};
|
|
14962
14906
|
|
|
14963
|
-
var iconPaths = /*#__PURE__*/Object.freeze({
|
|
14964
|
-
__proto__: null,
|
|
14965
|
-
iconCheck: iconCheck,
|
|
14966
|
-
iconCheckMedium: iconCheckMedium,
|
|
14967
|
-
iconChevronDown: iconChevronDown,
|
|
14968
|
-
iconChevronRight: iconChevronRight,
|
|
14969
|
-
iconCircle: iconCircle,
|
|
14970
|
-
iconCircleArrowDown: iconCircleArrowDown,
|
|
14971
|
-
iconCircleArrowUp: iconCircleArrowUp,
|
|
14972
|
-
iconCircleThin: iconCircleThin,
|
|
14973
|
-
iconDesktop: iconDesktop,
|
|
14974
|
-
iconDropdownArrow: iconDropdownArrow,
|
|
14975
|
-
iconExclamationSign: iconExclamationSign,
|
|
14976
|
-
iconGear: iconGear,
|
|
14977
|
-
iconMobilePhone: iconMobilePhone,
|
|
14978
|
-
iconOk: iconOk,
|
|
14979
|
-
iconPlus: iconPlus,
|
|
14980
|
-
iconRemove: iconRemove,
|
|
14981
|
-
iconStar: iconStar,
|
|
14982
|
-
iconTryAgain: iconTryAgain,
|
|
14983
|
-
iconTablet: iconTablet,
|
|
14984
|
-
iconTrash: iconTrash,
|
|
14985
|
-
iconUndo: iconUndo,
|
|
14986
|
-
iconMinus: iconMinus
|
|
14987
|
-
});
|
|
14988
|
-
|
|
14989
14907
|
/* eslint-disable @babel/no-invalid-this */
|
|
14990
14908
|
const add$1 = {
|
|
14991
14909
|
constrain: function () {
|
|
@@ -16878,6 +16796,15 @@ const Status = {
|
|
|
16878
16796
|
LOADED: "loaded",
|
|
16879
16797
|
FAILED: "failed"
|
|
16880
16798
|
};
|
|
16799
|
+
/**
|
|
16800
|
+
* Component to display an image (or other React components) while the desired
|
|
16801
|
+
* image is loading.
|
|
16802
|
+
*
|
|
16803
|
+
* Derived from
|
|
16804
|
+
* https://github.com/hzdg/react-imageloader/blob/master/src/index.js
|
|
16805
|
+
* to better suit our environment/build tools. Additionally, this one does
|
|
16806
|
+
* not introduce a wrapper element, which makes styling easier.
|
|
16807
|
+
*/
|
|
16881
16808
|
class ImageLoader extends React.Component {
|
|
16882
16809
|
constructor(props) {
|
|
16883
16810
|
super(props);
|
|
@@ -17432,7 +17359,7 @@ class SvgImage extends React.Component {
|
|
|
17432
17359
|
// Just use a normal image if a normal image is provided
|
|
17433
17360
|
if (!Util.isLabeledSVG(imageSrc)) {
|
|
17434
17361
|
if (responsive) {
|
|
17435
|
-
const wrapperClasses = classNames({
|
|
17362
|
+
const wrapperClasses = classNames$1({
|
|
17436
17363
|
zoomable: (width || 0) > ZOOMABLE_THRESHOLD,
|
|
17437
17364
|
"svg-image": true
|
|
17438
17365
|
});
|
|
@@ -18222,7 +18149,7 @@ const styles$C = StyleSheet.create({
|
|
|
18222
18149
|
},
|
|
18223
18150
|
":hover ~ div span[data-lint-inside-table]": {
|
|
18224
18151
|
backgroundColor: warningColor,
|
|
18225
|
-
color: white
|
|
18152
|
+
color: white
|
|
18226
18153
|
}
|
|
18227
18154
|
},
|
|
18228
18155
|
// This is how we position the hover target for inline lint.
|
|
@@ -18258,7 +18185,7 @@ const styles$C = StyleSheet.create({
|
|
|
18258
18185
|
// draw attention to the linty content.
|
|
18259
18186
|
":hover ~ span": {
|
|
18260
18187
|
backgroundColor: warningColor,
|
|
18261
|
-
color: white
|
|
18188
|
+
color: white
|
|
18262
18189
|
}
|
|
18263
18190
|
},
|
|
18264
18191
|
radioWidgetHoverTarget: {
|
|
@@ -18300,7 +18227,7 @@ const styles$C = StyleSheet.create({
|
|
|
18300
18227
|
// draw attention to the linty content.
|
|
18301
18228
|
":hover ~ span": {
|
|
18302
18229
|
backgroundColor: warningColor,
|
|
18303
|
-
color: white
|
|
18230
|
+
color: white
|
|
18304
18231
|
}
|
|
18305
18232
|
},
|
|
18306
18233
|
// This is the class for the lint indicator in the margin.
|
|
@@ -18337,10 +18264,10 @@ const styles$C = StyleSheet.create({
|
|
|
18337
18264
|
// When it is displayed, it goes on top!
|
|
18338
18265
|
zIndex: 1000,
|
|
18339
18266
|
// These styles control what the tooltip looks like
|
|
18340
|
-
color: white
|
|
18267
|
+
color: white,
|
|
18341
18268
|
backgroundColor: gray17,
|
|
18342
18269
|
opacity: 0.9,
|
|
18343
|
-
fontFamily: baseFontFamily
|
|
18270
|
+
fontFamily: baseFontFamily,
|
|
18344
18271
|
fontSize: "12px",
|
|
18345
18272
|
lineHeight: "15px",
|
|
18346
18273
|
width: "320px",
|
|
@@ -19342,7 +19269,7 @@ var preprocessTex = (texCode => texCode
|
|
|
19342
19269
|
|
|
19343
19270
|
const {
|
|
19344
19271
|
interactiveSizes
|
|
19345
|
-
} = constants
|
|
19272
|
+
} = constants;
|
|
19346
19273
|
|
|
19347
19274
|
// Note: these size cutoffs represent content-width cutoffs as specified in
|
|
19348
19275
|
// http://zpl.io/1mVmvU (broken link - we no longer use Zeplin)
|
|
@@ -19375,13 +19302,6 @@ const getInteractiveBoxFromSizeClass = sizeClass => {
|
|
|
19375
19302
|
return [interactiveSizes.defaultBoxSize, interactiveSizes.defaultBoxSize];
|
|
19376
19303
|
};
|
|
19377
19304
|
|
|
19378
|
-
var sizingUtils = /*#__PURE__*/Object.freeze({
|
|
19379
|
-
__proto__: null,
|
|
19380
|
-
containerSizeClass: containerSizeClass,
|
|
19381
|
-
getClassFromWidth: getClassFromWidth,
|
|
19382
|
-
getInteractiveBoxFromSizeClass: getInteractiveBoxFromSizeClass
|
|
19383
|
-
});
|
|
19384
|
-
|
|
19385
19305
|
class WidgetContainer extends React.Component {
|
|
19386
19306
|
constructor(...args) {
|
|
19387
19307
|
super(...args);
|
|
@@ -19432,7 +19352,7 @@ class WidgetContainer extends React.Component {
|
|
|
19432
19352
|
return this.props.shouldHighlight !== nextProps.shouldHighlight || this.props.type !== nextProps.type || this.state.widgetProps !== nextState.widgetProps || this.state.sizeClass !== nextState.sizeClass;
|
|
19433
19353
|
}
|
|
19434
19354
|
render() {
|
|
19435
|
-
let className = classNames({
|
|
19355
|
+
let className = classNames$1({
|
|
19436
19356
|
"perseus-widget-container": true,
|
|
19437
19357
|
"widget-highlight": this.props.shouldHighlight,
|
|
19438
19358
|
"widget-nohighlight": !this.props.shouldHighlight,
|
|
@@ -20025,7 +19945,7 @@ class Renderer extends React.Component {
|
|
|
20025
19945
|
if (this.translationIndex != null) {
|
|
20026
19946
|
className = null;
|
|
20027
19947
|
} else {
|
|
20028
|
-
className = classNames({
|
|
19948
|
+
className = classNames$1({
|
|
20029
19949
|
"perseus-paragraph-centered": !this._foundTextNodes,
|
|
20030
19950
|
// There is only one node being rendered,
|
|
20031
19951
|
// and it's a full-width widget.
|
|
@@ -20841,7 +20761,7 @@ class Renderer extends React.Component {
|
|
|
20841
20761
|
const markdownContents = this.outputMarkdown(parsedMarkdown, {
|
|
20842
20762
|
baseElements: apiOptions.baseElements
|
|
20843
20763
|
});
|
|
20844
|
-
const className = classNames({
|
|
20764
|
+
const className = classNames$1({
|
|
20845
20765
|
[ClassNames.RENDERER]: true,
|
|
20846
20766
|
[ClassNames.RESPONSIVE_RENDERER]: true,
|
|
20847
20767
|
[ClassNames.TWO_COLUMN_RENDERER]: this._isTwoColumn
|
|
@@ -21014,7 +20934,7 @@ const Triangle = props => {
|
|
|
21014
20934
|
width: 0,
|
|
21015
20935
|
position: "absolute",
|
|
21016
20936
|
left: props.left,
|
|
21017
|
-
top: props
|
|
20937
|
+
top: props.top,
|
|
21018
20938
|
borderLeft: borderLeft,
|
|
21019
20939
|
borderRight: borderRight,
|
|
21020
20940
|
borderTop: borderTop,
|
|
@@ -21095,6 +21015,47 @@ const HORIZONTAL_ALIGNMNENTS = {
|
|
|
21095
21015
|
arrowLeft: arrowSize => -arrowSize - 2
|
|
21096
21016
|
}
|
|
21097
21017
|
};
|
|
21018
|
+
/**
|
|
21019
|
+
* DEPRECATED! Use Wonder Blocks tooltip instead.
|
|
21020
|
+
*
|
|
21021
|
+
* A generic tooltip library for React.js
|
|
21022
|
+
*
|
|
21023
|
+
* ```
|
|
21024
|
+
* import Tooltip from "./tooltip";
|
|
21025
|
+
* <Tooltip
|
|
21026
|
+
* className="class-for-tooltip-contents"
|
|
21027
|
+
* horizontalPosition={HoriziontalDirection.Left}
|
|
21028
|
+
* horizontalAlign={HoriziontalDirection.Left}
|
|
21029
|
+
* verticalPosition={VerticalDirection.Top}
|
|
21030
|
+
* arrowSize={10} // arrow size in pixels
|
|
21031
|
+
* borderColor="#ccc" // color of the border for the tooltip
|
|
21032
|
+
* show={true} // whether the tooltip should currently be visible
|
|
21033
|
+
* targetContainerStyle={targetContainerStyle}
|
|
21034
|
+
* >
|
|
21035
|
+
* <TargetElementOfTheTooltip />
|
|
21036
|
+
* <TooltipContents1 />
|
|
21037
|
+
* <TooltipContents2 />
|
|
21038
|
+
* </Tooltip>
|
|
21039
|
+
* ```
|
|
21040
|
+
*
|
|
21041
|
+
* To show/hide the tooltip, the parent component should call the
|
|
21042
|
+
* `.show()` and `.hide()` methods of the tooltip when appropriate.
|
|
21043
|
+
* (These are usually set up as handlers of events on the target element.)
|
|
21044
|
+
*
|
|
21045
|
+
* Notes:
|
|
21046
|
+
* `className` should not specify a border; that is handled by `borderColor`
|
|
21047
|
+
* so that the arrow and tooltip match
|
|
21048
|
+
*
|
|
21049
|
+
* ```
|
|
21050
|
+
* __,,--``\\
|
|
21051
|
+
* _,,-''`` \\ ,
|
|
21052
|
+
* '----------_.------'-.___|\__
|
|
21053
|
+
* _.--''`` `)__ )__ @\__
|
|
21054
|
+
* ( .. ''---/___,,E/__,E'------`
|
|
21055
|
+
* `-''`''
|
|
21056
|
+
* Here be dragons.
|
|
21057
|
+
* ```
|
|
21058
|
+
*/
|
|
21098
21059
|
class Tooltip extends React.Component {
|
|
21099
21060
|
constructor(...args) {
|
|
21100
21061
|
super(...args);
|
|
@@ -21321,10 +21282,7 @@ class InputWithExamples extends React.Component {
|
|
|
21321
21282
|
return "- " + example;
|
|
21322
21283
|
}).join("\n");
|
|
21323
21284
|
const showExamples = this.props.shouldShowExamples && this.state.showExamples;
|
|
21324
|
-
return /*#__PURE__*/React.createElement(Tooltip
|
|
21325
|
-
// eslint-disable-next-line react/no-string-refs
|
|
21326
|
-
, {
|
|
21327
|
-
ref: "tooltip",
|
|
21285
|
+
return /*#__PURE__*/React.createElement(Tooltip, {
|
|
21328
21286
|
className: "perseus-formats-tooltip preview-measure",
|
|
21329
21287
|
horizontalPosition: HorizontalDirection.Left,
|
|
21330
21288
|
horizontalAlign: HorizontalDirection.Left,
|
|
@@ -24577,29 +24535,29 @@ var PassageRef$1 = {
|
|
|
24577
24535
|
* });
|
|
24578
24536
|
*/
|
|
24579
24537
|
const {
|
|
24580
|
-
pureXsMax
|
|
24581
|
-
pureSmMin
|
|
24582
|
-
pureSmMax
|
|
24583
|
-
pureMdMin
|
|
24584
|
-
pureMdMax
|
|
24585
|
-
pureLgMin
|
|
24586
|
-
pureLgMax
|
|
24587
|
-
pureXlMin
|
|
24588
|
-
} = constants
|
|
24538
|
+
pureXsMax,
|
|
24539
|
+
pureSmMin,
|
|
24540
|
+
pureSmMax,
|
|
24541
|
+
pureMdMin,
|
|
24542
|
+
pureMdMax,
|
|
24543
|
+
pureLgMin,
|
|
24544
|
+
pureLgMax,
|
|
24545
|
+
pureXlMin
|
|
24546
|
+
} = constants;
|
|
24589
24547
|
var mediaQueries = {
|
|
24590
|
-
xs: `@media screen and (max-width: ${pureXsMax
|
|
24591
|
-
sm: `@media screen and (min-width: ${pureSmMin
|
|
24592
|
-
md: `@media screen and (min-width: ${pureMdMin
|
|
24593
|
-
lg: `@media screen and (min-width: ${pureLgMin
|
|
24594
|
-
xl: `@media screen and (min-width: ${pureXlMin
|
|
24595
|
-
xsOrSmaller: `@media screen and (max-width: ${pureXsMax
|
|
24596
|
-
smOrSmaller: `@media screen and (max-width: ${pureSmMax
|
|
24597
|
-
mdOrSmaller: `@media screen and (max-width: ${pureMdMax
|
|
24598
|
-
lgOrSmaller: `@media screen and (max-width: ${pureLgMax
|
|
24599
|
-
smOrLarger: `@media screen and (min-width: ${pureSmMin
|
|
24600
|
-
mdOrLarger: `@media screen and (min-width: ${pureMdMin
|
|
24601
|
-
lgOrLarger: `@media screen and (min-width: ${pureLgMin
|
|
24602
|
-
xlOrLarger: `@media screen and (min-width: ${pureXlMin
|
|
24548
|
+
xs: `@media screen and (max-width: ${pureXsMax})`,
|
|
24549
|
+
sm: `@media screen and (min-width: ${pureSmMin}) and ` + `(max-width: ${pureSmMax})`,
|
|
24550
|
+
md: `@media screen and (min-width: ${pureMdMin}) and ` + `(max-width: ${pureMdMax})`,
|
|
24551
|
+
lg: `@media screen and (min-width: ${pureLgMin}) and ` + `(max-width: ${pureLgMax})`,
|
|
24552
|
+
xl: `@media screen and (min-width: ${pureXlMin})`,
|
|
24553
|
+
xsOrSmaller: `@media screen and (max-width: ${pureXsMax})`,
|
|
24554
|
+
smOrSmaller: `@media screen and (max-width: ${pureSmMax})`,
|
|
24555
|
+
mdOrSmaller: `@media screen and (max-width: ${pureMdMax})`,
|
|
24556
|
+
lgOrSmaller: `@media screen and (max-width: ${pureLgMax})`,
|
|
24557
|
+
smOrLarger: `@media screen and (min-width: ${pureSmMin})`,
|
|
24558
|
+
mdOrLarger: `@media screen and (min-width: ${pureMdMin})`,
|
|
24559
|
+
lgOrLarger: `@media screen and (min-width: ${pureLgMin})`,
|
|
24560
|
+
xlOrLarger: `@media screen and (min-width: ${pureXlMin})`
|
|
24603
24561
|
};
|
|
24604
24562
|
|
|
24605
24563
|
const {
|
|
@@ -24609,7 +24567,7 @@ const {
|
|
|
24609
24567
|
checkedColor,
|
|
24610
24568
|
circleSize,
|
|
24611
24569
|
radioMarginWidth
|
|
24612
|
-
} = constants
|
|
24570
|
+
} = constants;
|
|
24613
24571
|
var sharedStyles = StyleSheet.create({
|
|
24614
24572
|
perseusInteractive: {
|
|
24615
24573
|
zIndex: zIndexInteractiveComponent,
|
|
@@ -24841,6 +24799,37 @@ const BASE_ICON_SIZE = 10;
|
|
|
24841
24799
|
// If you pass in an object you need to specify an SVG path to
|
|
24842
24800
|
// render along with the width and height of the path (to ensure
|
|
24843
24801
|
// that it gets scaled correctly).
|
|
24802
|
+
/**
|
|
24803
|
+
* An SVG Icon
|
|
24804
|
+
*
|
|
24805
|
+
* This component is designed to take in SVG paths and render icons based upon
|
|
24806
|
+
* them. If you are looking for an icon that we've used before you should look
|
|
24807
|
+
* in `icon-paths.js` which is a reference file for all the SVG paths that
|
|
24808
|
+
* we've used. You'll need to copy the object from that file into whichever
|
|
24809
|
+
* file you're using the icon and explicitly pass it in to the <Icon/> React
|
|
24810
|
+
* component.
|
|
24811
|
+
*
|
|
24812
|
+
* Sample usage:
|
|
24813
|
+
*
|
|
24814
|
+
* ```
|
|
24815
|
+
* const dropdownIcon = `M5,6L0,0L10,0`;
|
|
24816
|
+
* <Icon icon={dropdownIcon} />
|
|
24817
|
+
* ```
|
|
24818
|
+
*
|
|
24819
|
+
* Or:
|
|
24820
|
+
*
|
|
24821
|
+
* ```
|
|
24822
|
+
* const dropdownIcon = {
|
|
24823
|
+
* path: `M5,6L0,0L10,0`,
|
|
24824
|
+
* height: 10,
|
|
24825
|
+
* width: 10,
|
|
24826
|
+
* };
|
|
24827
|
+
* <Icon icon={dropdownIcon} size={20} />
|
|
24828
|
+
* ```
|
|
24829
|
+
*
|
|
24830
|
+
* If you want to add an entirely new icon please read the note inside
|
|
24831
|
+
* the `icon-paths.ts` file.
|
|
24832
|
+
*/
|
|
24844
24833
|
class Icon extends React.Component {
|
|
24845
24834
|
render() {
|
|
24846
24835
|
const {
|
|
@@ -24962,7 +24951,7 @@ function getA11yText(letter, checked, correct, crossedOut, showCorrectness, stri
|
|
|
24962
24951
|
*/
|
|
24963
24952
|
const FocusRing = function FocusRing({
|
|
24964
24953
|
visible = true,
|
|
24965
|
-
color = kaGreen
|
|
24954
|
+
color = kaGreen,
|
|
24966
24955
|
multipleSelect = false,
|
|
24967
24956
|
children
|
|
24968
24957
|
}) {
|
|
@@ -25063,7 +25052,7 @@ function ChoiceInner(props) {
|
|
|
25063
25052
|
} = usePerseusI18n();
|
|
25064
25053
|
const letter = getChoiceLetter(pos, strings);
|
|
25065
25054
|
if (!showCorrectness) {
|
|
25066
|
-
return letter;
|
|
25055
|
+
return /*#__PURE__*/React.createElement("span", null, letter);
|
|
25067
25056
|
}
|
|
25068
25057
|
if (correct) {
|
|
25069
25058
|
return /*#__PURE__*/React.createElement(InlineIcon, _extends({}, iconCheck, {
|
|
@@ -25090,7 +25079,7 @@ function getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, cor
|
|
|
25090
25079
|
backgroundColor = "transparent";
|
|
25091
25080
|
} else if (checked) {
|
|
25092
25081
|
const bg = showCorrectness && correct ? color.green : color.blue;
|
|
25093
|
-
color$1 = white
|
|
25082
|
+
color$1 = white;
|
|
25094
25083
|
backgroundColor = bg;
|
|
25095
25084
|
borderColor = bg;
|
|
25096
25085
|
} else {
|
|
@@ -25133,7 +25122,6 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
25133
25122
|
visible: focused || hovered,
|
|
25134
25123
|
multipleSelect: multipleSelect
|
|
25135
25124
|
}, /*#__PURE__*/React.createElement("div", {
|
|
25136
|
-
// @ts-expect-error - TS2322 - Type '{ backgroundColor: string | null | undefined; borderColor: string; color: string; borderRadius: number; }' is not assignable to type 'Properties<string | number, string & {}>'.
|
|
25137
25125
|
style: dynamicStyles,
|
|
25138
25126
|
"data-testid": "choice-icon__library-choice-icon",
|
|
25139
25127
|
className: css(styles$s.circle, showCorrectness && correct && styles$s.circleCorrect, showCorrectness && !correct && styles$s.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$s.circleIncorrectAnswered)
|
|
@@ -25168,7 +25156,7 @@ const styles$s = StyleSheet.create({
|
|
|
25168
25156
|
borderStyle: "solid",
|
|
25169
25157
|
borderWidth: 2,
|
|
25170
25158
|
// The default icons have letters in them. Style those letters.
|
|
25171
|
-
fontFamily: baseFontFamily
|
|
25159
|
+
fontFamily: baseFontFamily,
|
|
25172
25160
|
// NOTE(emily): We explicitly set the font weight instead of using the
|
|
25173
25161
|
// "bold font family" so that characters which fall back to the default
|
|
25174
25162
|
// font get bolded too.
|
|
@@ -25328,8 +25316,8 @@ const Choice = function Choice(props) {
|
|
|
25328
25316
|
crossedOut: updatedCrossedOut
|
|
25329
25317
|
});
|
|
25330
25318
|
}
|
|
25331
|
-
const descriptionClassName = classNames("description", css(styles$q.description));
|
|
25332
|
-
const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$q.rationale));
|
|
25319
|
+
const descriptionClassName = classNames$1("description", css(styles$q.description));
|
|
25320
|
+
const rationaleClassName = classNames$1("perseus-radio-rationale-content", css(styles$q.rationale));
|
|
25333
25321
|
|
|
25334
25322
|
// We want to show the choices as dimmed out when the choices are disabled.
|
|
25335
25323
|
// However, we don't want to do this when we're in review mode in the
|
|
@@ -25679,8 +25667,8 @@ const BaseRadio = function BaseRadio({
|
|
|
25679
25667
|
const isMobile = apiOptions.isMobile;
|
|
25680
25668
|
const firstChoiceHighlighted = choices[0].highlighted;
|
|
25681
25669
|
const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
|
|
25682
|
-
const className = classNames("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$p.radio, styles$p.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$p.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$p.radioContainerLastHighlighted));
|
|
25683
|
-
const instructionsClassName = classNames("instructions", css(styles$p.instructions, isMobile && styles$p.instructionsMobile));
|
|
25670
|
+
const className = classNames$1("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$p.radio, styles$p.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$p.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$p.radioContainerLastHighlighted));
|
|
25671
|
+
const instructionsClassName = classNames$1("instructions", css(styles$p.instructions, isMobile && styles$p.instructionsMobile));
|
|
25684
25672
|
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect, strings);
|
|
25685
25673
|
const responsiveClassName = css(styles$p.responsiveFieldset);
|
|
25686
25674
|
const fieldset = /*#__PURE__*/React.createElement("fieldset", {
|
|
@@ -25746,7 +25734,7 @@ const BaseRadio = function BaseRadio({
|
|
|
25746
25734
|
if (reviewMode && reviewModeRubric) {
|
|
25747
25735
|
correctnessClass = reviewModeRubric.choices[i].correct ? ClassNames.CORRECT : ClassNames.INCORRECT;
|
|
25748
25736
|
}
|
|
25749
|
-
const className = classNames(aphroditeClassName(choice.checked),
|
|
25737
|
+
const className = classNames$1(aphroditeClassName(choice.checked),
|
|
25750
25738
|
// TODO(aria): Make test case for these API
|
|
25751
25739
|
// classNames
|
|
25752
25740
|
ClassNames.RADIO.OPTION, choice.checked && ClassNames.RADIO.SELECTED, correctnessClass);
|
|
@@ -26539,7 +26527,7 @@ class Categorizer extends React.Component {
|
|
|
26539
26527
|
|
|
26540
26528
|
// TODO(benkomalo): kill CSS-based styling and move everything to
|
|
26541
26529
|
// aphrodite.
|
|
26542
|
-
const extraClassNames = classNames({
|
|
26530
|
+
const extraClassNames = classNames$1({
|
|
26543
26531
|
"categorizer-container": true,
|
|
26544
26532
|
"static-mode": this.props.static
|
|
26545
26533
|
});
|
|
@@ -27433,7 +27421,7 @@ class GradedGroup extends React.Component {
|
|
|
27433
27421
|
gradeStatus = this.context.strings.incorrect;
|
|
27434
27422
|
}
|
|
27435
27423
|
const mobileClass = this.props.inGradedGroupSet ? css(styles$j.gradedGroupInSet) : css(styles$j.gradedGroup);
|
|
27436
|
-
const classes = classNames({
|
|
27424
|
+
const classes = classNames$1({
|
|
27437
27425
|
[mobileClass]: apiOptions.isMobile,
|
|
27438
27426
|
"perseus-graded-group": true,
|
|
27439
27427
|
"answer-correct": apiOptions.isMobile ? false : this.state.status === GRADING_STATUSES.correct,
|
|
@@ -27548,7 +27536,7 @@ const styles$j = StyleSheet.create({
|
|
|
27548
27536
|
gradedGroup: {
|
|
27549
27537
|
borderTop: `1px solid ${gray76}`,
|
|
27550
27538
|
borderBottom: `1px solid ${gray76}`,
|
|
27551
|
-
backgroundColor: tableBackgroundAccent
|
|
27539
|
+
backgroundColor: tableBackgroundAccent,
|
|
27552
27540
|
marginLeft: negativePhoneMargin,
|
|
27553
27541
|
marginRight: negativePhoneMargin,
|
|
27554
27542
|
paddingBottom: phoneMargin,
|
|
@@ -27612,7 +27600,7 @@ class Indicators extends React.Component {
|
|
|
27612
27600
|
return /*#__PURE__*/React.createElement("ul", {
|
|
27613
27601
|
// reduntantly add class name for use in .less files--
|
|
27614
27602
|
// the styles object key gets hashed
|
|
27615
|
-
className: classNames(css(styles$i.indicatorContainer), "indicatorContainer")
|
|
27603
|
+
className: classNames$1(css(styles$i.indicatorContainer), "indicatorContainer")
|
|
27616
27604
|
}, this.props.gradedGroups.map(({
|
|
27617
27605
|
title
|
|
27618
27606
|
}, i) => /*#__PURE__*/React.createElement("li", {
|
|
@@ -27827,7 +27815,7 @@ const styles$i = StyleSheet.create({
|
|
|
27827
27815
|
container: {
|
|
27828
27816
|
borderTop: `1px solid ${gray76}`,
|
|
27829
27817
|
borderBottom: `1px solid ${gray76}`,
|
|
27830
|
-
backgroundColor: tableBackgroundAccent
|
|
27818
|
+
backgroundColor: tableBackgroundAccent,
|
|
27831
27819
|
marginLeft: negativePhoneMargin,
|
|
27832
27820
|
marginRight: negativePhoneMargin,
|
|
27833
27821
|
paddingBottom: phoneMargin,
|
|
@@ -28435,21 +28423,6 @@ const typeToButton = type => {
|
|
|
28435
28423
|
};
|
|
28436
28424
|
};
|
|
28437
28425
|
|
|
28438
|
-
var util = /*#__PURE__*/Object.freeze({
|
|
28439
|
-
__proto__: null,
|
|
28440
|
-
DEFAULT_BACKGROUND_IMAGE: DEFAULT_BACKGROUND_IMAGE,
|
|
28441
|
-
allTypes: allTypes,
|
|
28442
|
-
functionForType: functionForType,
|
|
28443
|
-
getEquationString: getEquationString,
|
|
28444
|
-
pointsFromNormalized: pointsFromNormalized,
|
|
28445
|
-
maybePointsFromNormalized: maybePointsFromNormalized,
|
|
28446
|
-
defaultPlotProps: defaultPlotProps,
|
|
28447
|
-
chooseType: chooseType,
|
|
28448
|
-
getGridAndSnapSteps: getGridAndSnapSteps,
|
|
28449
|
-
DEFAULT_GRAPHER_PROPS: DEFAULT_GRAPHER_PROPS,
|
|
28450
|
-
typeToButton: typeToButton
|
|
28451
|
-
});
|
|
28452
|
-
|
|
28453
28426
|
function getCoefficientsByType(data) {
|
|
28454
28427
|
if (data.type === "exponential" || data.type === "logarithm") {
|
|
28455
28428
|
const grader = functionForType(data.type);
|
|
@@ -29006,7 +28979,7 @@ class Group extends React.Component {
|
|
|
29006
28979
|
// TODO(mdr): Widgets inside this Renderer are not discoverable through
|
|
29007
28980
|
// the parent Renderer's `findWidgets` function.
|
|
29008
28981
|
return /*#__PURE__*/React.createElement("div", {
|
|
29009
|
-
className: classNames({
|
|
28982
|
+
className: classNames$1({
|
|
29010
28983
|
"perseus-group": true,
|
|
29011
28984
|
"perseus-group-valid-answer": isValid,
|
|
29012
28985
|
"perseus-group-invalid-answer": isInvalid
|
|
@@ -29274,7 +29247,7 @@ class ImageWidget extends React.Component {
|
|
|
29274
29247
|
}
|
|
29275
29248
|
_title = `**${_title}** `;
|
|
29276
29249
|
}
|
|
29277
|
-
const className = classNames({
|
|
29250
|
+
const className = classNames$1({
|
|
29278
29251
|
"perseus-image-caption": true,
|
|
29279
29252
|
"has-title": !!_title
|
|
29280
29253
|
});
|
|
@@ -30982,6 +30955,10 @@ const HiddenIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
|
30982
30955
|
}, /*#__PURE__*/React.createElement("path", {
|
|
30983
30956
|
d: "M0 0h24v24H0z"
|
|
30984
30957
|
}))));
|
|
30958
|
+
/**
|
|
30959
|
+
* A "heads-up display" (HUD) indicator that includes a short message (usually
|
|
30960
|
+
* used for linting errors). The indicator can be disabled.
|
|
30961
|
+
*/
|
|
30985
30962
|
const HUD = ({
|
|
30986
30963
|
message,
|
|
30987
30964
|
enabled,
|
|
@@ -31013,7 +30990,7 @@ const styles$g = StyleSheet.create({
|
|
|
31013
30990
|
fontFamily: boldFontFamily,
|
|
31014
30991
|
fontSize: "15px",
|
|
31015
30992
|
lineHeight: "18px",
|
|
31016
|
-
color: white
|
|
30993
|
+
color: white,
|
|
31017
30994
|
userSelect: "none",
|
|
31018
30995
|
borderWidth: 0 // <button> gives us a border by default
|
|
31019
30996
|
},
|
|
@@ -31202,18 +31179,24 @@ const {
|
|
|
31202
31179
|
const toNumericString = KhanMath.toNumericString;
|
|
31203
31180
|
const getNumericFormat = KhanMath.getNumericFormat;
|
|
31204
31181
|
|
|
31205
|
-
|
|
31182
|
+
/**
|
|
31183
|
+
* An input box that accepts only numeric strings
|
|
31206
31184
|
*
|
|
31207
|
-
* Calls onChange(value, format) for valid numbers.
|
|
31208
|
-
*
|
|
31185
|
+
* Calls `onChange(value, format)` for valid numbers.
|
|
31186
|
+
*
|
|
31187
|
+
* Reverts to the current value `onBlur` or on [ENTER],
|
|
31209
31188
|
* but maintains the format (i.e. 3/2, 1 1/2, 150%)
|
|
31210
|
-
*
|
|
31211
|
-
*
|
|
31212
|
-
*
|
|
31213
|
-
*
|
|
31214
|
-
* If
|
|
31215
|
-
*
|
|
31216
|
-
*
|
|
31189
|
+
*
|
|
31190
|
+
* Accepts empty input and sends it to `onChange` as `null` if no numeric
|
|
31191
|
+
* placeholder is set.
|
|
31192
|
+
*
|
|
31193
|
+
* If given a `checkValidity` function, will turn the background/outline red
|
|
31194
|
+
* when invalid.
|
|
31195
|
+
*
|
|
31196
|
+
* If `useArrowKeys` is set to `true`, up/down arrows will increment/decrement
|
|
31197
|
+
* integers.
|
|
31198
|
+
*
|
|
31199
|
+
* Optionally takes a `size` (`"mini"`, `"small"`,` `"normal"`)
|
|
31217
31200
|
*/
|
|
31218
31201
|
class NumberInput extends React.Component {
|
|
31219
31202
|
constructor(...args) {
|
|
@@ -31335,7 +31318,7 @@ class NumberInput extends React.Component {
|
|
|
31335
31318
|
}
|
|
31336
31319
|
}
|
|
31337
31320
|
render() {
|
|
31338
|
-
let classes = classNames({
|
|
31321
|
+
let classes = classNames$1({
|
|
31339
31322
|
"number-input": true,
|
|
31340
31323
|
"invalid-input": !this._checkValidity(this.props.value),
|
|
31341
31324
|
mini: this.props.size === "mini",
|
|
@@ -31372,7 +31355,7 @@ NumberInput.propTypes = {
|
|
|
31372
31355
|
onChange: PropTypes.func.isRequired,
|
|
31373
31356
|
onFormatChange: PropTypes.func,
|
|
31374
31357
|
checkValidity: PropTypes.func,
|
|
31375
|
-
size: PropTypes.
|
|
31358
|
+
size: PropTypes.oneOf(["mini", "small", "normal"]),
|
|
31376
31359
|
label: PropTypes.oneOf(["put your labels outside your inputs!"])
|
|
31377
31360
|
};
|
|
31378
31361
|
NumberInput.defaultProps = {
|
|
@@ -31386,8 +31369,8 @@ NumberInput.defaultProps = {
|
|
|
31386
31369
|
|
|
31387
31370
|
const truth = () => true;
|
|
31388
31371
|
|
|
31389
|
-
|
|
31390
|
-
*
|
|
31372
|
+
/**
|
|
31373
|
+
* A minor abstraction on top of `NumberInput` for ranges
|
|
31391
31374
|
*/
|
|
31392
31375
|
class RangeInput extends React.Component {
|
|
31393
31376
|
constructor(...args) {
|
|
@@ -32094,7 +32077,12 @@ const actions = {
|
|
|
32094
32077
|
},
|
|
32095
32078
|
polygon: {
|
|
32096
32079
|
movePoint,
|
|
32097
|
-
moveAll
|
|
32080
|
+
moveAll,
|
|
32081
|
+
addPoint,
|
|
32082
|
+
removePoint,
|
|
32083
|
+
focusPoint,
|
|
32084
|
+
blurPoint,
|
|
32085
|
+
clickPoint
|
|
32098
32086
|
},
|
|
32099
32087
|
quadratic: {
|
|
32100
32088
|
movePoint
|
|
@@ -32233,11 +32221,333 @@ function reinitialize(params) {
|
|
|
32233
32221
|
};
|
|
32234
32222
|
}
|
|
32235
32223
|
|
|
32224
|
+
/**
|
|
32225
|
+
* Wrapper with Mafs transform styles for SVG elements.
|
|
32226
|
+
* Scales and translates the SVG element to match the Mafs view.
|
|
32227
|
+
* Use if you do not need/want to use the hook in `use-transform.ts`.
|
|
32228
|
+
*/
|
|
32229
|
+
const MafsCssTransformWrapper = ({
|
|
32230
|
+
children
|
|
32231
|
+
}) => /*#__PURE__*/React.createElement("g", {
|
|
32232
|
+
style: {
|
|
32233
|
+
transform: `var(--mafs-view-transform) var(--mafs-user-transform)`
|
|
32234
|
+
}
|
|
32235
|
+
}, children);
|
|
32236
|
+
|
|
32237
|
+
const _excluded$1 = ["children"];
|
|
32238
|
+
const TextLabel = _ref => {
|
|
32239
|
+
let {
|
|
32240
|
+
children
|
|
32241
|
+
} = _ref,
|
|
32242
|
+
rest = _objectWithoutPropertiesLoose(_ref, _excluded$1);
|
|
32243
|
+
return /*#__PURE__*/React__default.createElement(Text$1, _extends({
|
|
32244
|
+
size: 16,
|
|
32245
|
+
svgTextProps: {
|
|
32246
|
+
filter: "url(#background)",
|
|
32247
|
+
fontWeight: "bold"
|
|
32248
|
+
}
|
|
32249
|
+
}, rest), children);
|
|
32250
|
+
};
|
|
32251
|
+
const SvgDefs = () => /*#__PURE__*/React__default.createElement("defs", null, /*#__PURE__*/React__default.createElement("filter", {
|
|
32252
|
+
id: "background",
|
|
32253
|
+
x: "-5%",
|
|
32254
|
+
width: "110%",
|
|
32255
|
+
y: "0%",
|
|
32256
|
+
height: "100%"
|
|
32257
|
+
}, /*#__PURE__*/React__default.createElement("feFlood", {
|
|
32258
|
+
floodColor: "#FFF",
|
|
32259
|
+
floodOpacity: "0.64"
|
|
32260
|
+
}), /*#__PURE__*/React__default.createElement("feComposite", {
|
|
32261
|
+
operator: "over",
|
|
32262
|
+
in: "SourceGraphic"
|
|
32263
|
+
})));
|
|
32264
|
+
|
|
32265
|
+
const PolygonAngle = ({
|
|
32266
|
+
centerPoint,
|
|
32267
|
+
endPoints,
|
|
32268
|
+
range,
|
|
32269
|
+
polygonLines,
|
|
32270
|
+
showAngles,
|
|
32271
|
+
snapTo
|
|
32272
|
+
}) => {
|
|
32273
|
+
const [centerX, centerY] = centerPoint;
|
|
32274
|
+
const areClockwise = clockwise$1([centerPoint, ...endPoints]);
|
|
32275
|
+
const [[startX, startY], [endX, endY]] = areClockwise ? endPoints : endPoints.reverse();
|
|
32276
|
+
const radius = 0.3;
|
|
32277
|
+
const a = vec.dist(centerPoint, endPoints[0]);
|
|
32278
|
+
const b = vec.dist(centerPoint, endPoints[1]);
|
|
32279
|
+
const c = vec.dist(endPoints[0], endPoints[1]);
|
|
32280
|
+
|
|
32281
|
+
// Law of cosines
|
|
32282
|
+
const angle = Math.acos((a ** 2 + b ** 2 - c ** 2) / (2 * a * b));
|
|
32283
|
+
const y1 = centerY + (startY - centerY) / a * radius;
|
|
32284
|
+
const x2 = centerX + (endX - centerX) / b * radius;
|
|
32285
|
+
const x1 = centerX + (startX - centerX) / a * radius;
|
|
32286
|
+
const y2 = centerY + (endY - centerY) / b * radius;
|
|
32287
|
+
|
|
32288
|
+
// Fourth point that would create a rhomboid
|
|
32289
|
+
// Used to calculate the inside of the angle and to create square
|
|
32290
|
+
const [x3, y3] = vec.add(centerPoint, vec.add(vec.sub([x1, y1], centerPoint), vec.sub([x2, y2], centerPoint)));
|
|
32291
|
+
if (!showAngles) {
|
|
32292
|
+
return isRightPolygonAngle(angle) ? /*#__PURE__*/React.createElement(RightAngleSquare, {
|
|
32293
|
+
start: [x1, y1],
|
|
32294
|
+
vertex: [x2, y2],
|
|
32295
|
+
end: [x3, y3]
|
|
32296
|
+
}) : null;
|
|
32297
|
+
}
|
|
32298
|
+
|
|
32299
|
+
// Midpoint betwen ends of arc
|
|
32300
|
+
const isOutside = shouldDrawArcOutside([x3, y3], centerPoint, range, polygonLines);
|
|
32301
|
+
const largeArcFlag = isOutside ? 1 : 0;
|
|
32302
|
+
const sweepFlag = isOutside ? 1 : 0;
|
|
32303
|
+
const arc = `M ${x1} ${y1} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${x2} ${y2}`;
|
|
32304
|
+
let angleInDegrees = angle * (180 / Math.PI);
|
|
32305
|
+
// If we have triggered "largArcFlag", the angle should be greater than 180
|
|
32306
|
+
if (isOutside) {
|
|
32307
|
+
angleInDegrees = 360 - angleInDegrees;
|
|
32308
|
+
}
|
|
32309
|
+
|
|
32310
|
+
// Only want to show whole numbers when in angles mode
|
|
32311
|
+
const angleLabelNumber = parseFloat(angleInDegrees.toFixed(snapTo === "angles" ? 0 : 1));
|
|
32312
|
+
const angleLabel = Number.isInteger(angleLabelNumber) ? angleLabelNumber : "≈ " + angleLabelNumber;
|
|
32313
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("filter", {
|
|
32314
|
+
id: "background",
|
|
32315
|
+
x: "-5%",
|
|
32316
|
+
width: "110%",
|
|
32317
|
+
y: "0%",
|
|
32318
|
+
height: "100%"
|
|
32319
|
+
}, /*#__PURE__*/React.createElement("feFlood", {
|
|
32320
|
+
floodColor: "#FFF",
|
|
32321
|
+
floodOpacity: "0.5"
|
|
32322
|
+
}), /*#__PURE__*/React.createElement("feComposite", {
|
|
32323
|
+
operator: "over",
|
|
32324
|
+
in: "SourceGraphic"
|
|
32325
|
+
}))), !isOutside && isRightAngle(angle) ? /*#__PURE__*/React.createElement(RightAngleSquare, {
|
|
32326
|
+
start: [x1, y1],
|
|
32327
|
+
vertex: [x2, y2],
|
|
32328
|
+
end: [x3, y3]
|
|
32329
|
+
}) : /*#__PURE__*/React.createElement(Arc, {
|
|
32330
|
+
arc: arc
|
|
32331
|
+
}), /*#__PURE__*/React.createElement(TextLabel, {
|
|
32332
|
+
x: x3,
|
|
32333
|
+
y: y3,
|
|
32334
|
+
attach: y3 - centerY > 0 ? "s" : "n",
|
|
32335
|
+
attachDistance: Math.abs(y3 - centerY) < 0.2 || vec.dist([x3, y3], centerPoint) < 0.3 ? 20 : 10
|
|
32336
|
+
}, angleLabel, "\xB0"));
|
|
32337
|
+
};
|
|
32338
|
+
const Angle = ({
|
|
32339
|
+
vertex,
|
|
32340
|
+
coords,
|
|
32341
|
+
showAngles,
|
|
32342
|
+
allowReflexAngles,
|
|
32343
|
+
range
|
|
32344
|
+
}) => {
|
|
32345
|
+
// Check if the points are clockwise or not, depending on whether we allow reflex angles
|
|
32346
|
+
const areClockwise = clockwise$1([...coords, vertex]);
|
|
32347
|
+
const shouldReverseCoords = areClockwise && !allowReflexAngles;
|
|
32348
|
+
|
|
32349
|
+
// Reverse the coordinates accordingly to ensure the angle is calculated correctly
|
|
32350
|
+
const clockwiseCoords = shouldReverseCoords ? coords : coords.reverse();
|
|
32351
|
+
|
|
32352
|
+
// Calculate the angles between the two points
|
|
32353
|
+
const startAngle = getAngleFromVertex(clockwiseCoords[0], vertex);
|
|
32354
|
+
const endAngle = getAngleFromVertex(clockwiseCoords[1], vertex);
|
|
32355
|
+
const angle = (startAngle + 360 - endAngle) % 360;
|
|
32356
|
+
|
|
32357
|
+
// Check if the angle is reflexive
|
|
32358
|
+
const isReflexive = angle > 180;
|
|
32359
|
+
|
|
32360
|
+
// Break out the necessary points for the arc calculation
|
|
32361
|
+
const [centerX, centerY] = vertex;
|
|
32362
|
+
const [point1, point2] = clockwiseCoords;
|
|
32363
|
+
const [startX, startY] = point1;
|
|
32364
|
+
const [endX, endY] = point2;
|
|
32365
|
+
const a = vec.dist(vertex, point1);
|
|
32366
|
+
const b = vec.dist(vertex, point2);
|
|
32367
|
+
|
|
32368
|
+
// Set the radius of the arc
|
|
32369
|
+
const radius = 2;
|
|
32370
|
+
|
|
32371
|
+
// Calculate the end points of the arc
|
|
32372
|
+
const y1 = centerY + (startY - centerY) / a * radius;
|
|
32373
|
+
const x2 = centerX + (endX - centerX) / b * radius;
|
|
32374
|
+
const x1 = centerX + (startX - centerX) / a * radius;
|
|
32375
|
+
const y2 = centerY + (endY - centerY) / b * radius;
|
|
32376
|
+
|
|
32377
|
+
// Used to calculate the inside of the angle and to create square
|
|
32378
|
+
const [x3, y3] = vec.add(vertex, vec.add(vec.sub([x1, y1], vertex), vec.sub([x2, y2], vertex)));
|
|
32379
|
+
|
|
32380
|
+
// Determine whether the arc should be drawn outside the angle
|
|
32381
|
+
const isOutside = shouldDrawArcOutside([x3, y3], vertex, range, [[vertex, point1], [vertex, point2]]);
|
|
32382
|
+
|
|
32383
|
+
// Determine the flags for the arc
|
|
32384
|
+
// If the angle is outside OR reflexive, we want to draw a large arc
|
|
32385
|
+
// If the angle is outside AND reflexive, we want to sweep the arc
|
|
32386
|
+
const largeArcFlag = isOutside || isReflexive ? 1 : 0;
|
|
32387
|
+
const sweepFlag = isOutside && isReflexive ? 1 : 0;
|
|
32388
|
+
|
|
32389
|
+
// Create the SVG path for the arc
|
|
32390
|
+
const arc = `M ${x1} ${y1} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${x2} ${y2}`;
|
|
32391
|
+
|
|
32392
|
+
// We only ever want to show whole angles
|
|
32393
|
+
const angleLabel = parseFloat(angle.toFixed(0)); // Only want to show whole angles
|
|
32394
|
+
|
|
32395
|
+
// Calculate the text position based on the angle and whether we allow reflex angles
|
|
32396
|
+
// Let's try the angle bisector method to find the midpoint of the arc
|
|
32397
|
+
const [textX, textY] = calculateBisectorPoint(point1, point2, vertex, isReflexive, allowReflexAngles, radius);
|
|
32398
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("filter", {
|
|
32399
|
+
id: "background",
|
|
32400
|
+
x: "-5%",
|
|
32401
|
+
width: "110%",
|
|
32402
|
+
y: "0%",
|
|
32403
|
+
height: "100%"
|
|
32404
|
+
}, /*#__PURE__*/React.createElement("feFlood", {
|
|
32405
|
+
floodColor: "#FFF",
|
|
32406
|
+
floodOpacity: "0.5"
|
|
32407
|
+
}), /*#__PURE__*/React.createElement("feComposite", {
|
|
32408
|
+
operator: "over",
|
|
32409
|
+
in: "SourceGraphic"
|
|
32410
|
+
}))), isRightAngle(angle) ? /*#__PURE__*/React.createElement(RightAngleSquare, {
|
|
32411
|
+
start: [x1, y1],
|
|
32412
|
+
vertex: [x2, y2],
|
|
32413
|
+
end: [x3, y3],
|
|
32414
|
+
className: "arc-right-angle"
|
|
32415
|
+
}) : /*#__PURE__*/React.createElement(Arc, {
|
|
32416
|
+
arc: arc,
|
|
32417
|
+
className: "angle-arc"
|
|
32418
|
+
}), showAngles && /*#__PURE__*/React.createElement(TextLabel, {
|
|
32419
|
+
x: textX,
|
|
32420
|
+
y: textY,
|
|
32421
|
+
color: color.blue
|
|
32422
|
+
}, angleLabel, "\xB0"));
|
|
32423
|
+
};
|
|
32424
|
+
|
|
32425
|
+
/**
|
|
32426
|
+
* This is broken out into its own component so that it can be used for an early return
|
|
32427
|
+
* (see line 55 or https://github.com/Khan/perseus/blob/84bbd882b11d16871e1b813a0b901f3b903d5479/packages/perseus/src/widgets/interactive-graphs/graphs/components/angle.tsx#L53-L57)
|
|
32428
|
+
*/
|
|
32429
|
+
const RightAngleSquare = ({
|
|
32430
|
+
start: [x1, y1],
|
|
32431
|
+
vertex: [x2, y2],
|
|
32432
|
+
end: [x3, y3],
|
|
32433
|
+
className
|
|
32434
|
+
}) => /*#__PURE__*/React.createElement(MafsCssTransformWrapper, null, /*#__PURE__*/React.createElement("path", {
|
|
32435
|
+
d: `M ${x1} ${y1} L ${x3} ${y3} M ${x3} ${y3} L ${x2} ${y2}`,
|
|
32436
|
+
strokeWidth: 0.02,
|
|
32437
|
+
fill: "none",
|
|
32438
|
+
className: className
|
|
32439
|
+
}));
|
|
32440
|
+
|
|
32441
|
+
// We're conditionally adding the class name here so that we can style the arc differently
|
|
32442
|
+
// based on whether it's an angle or a polygon angle
|
|
32443
|
+
const Arc = ({
|
|
32444
|
+
arc,
|
|
32445
|
+
className
|
|
32446
|
+
}) => {
|
|
32447
|
+
return /*#__PURE__*/React.createElement(MafsCssTransformWrapper, null, /*#__PURE__*/React.createElement("path", {
|
|
32448
|
+
d: arc,
|
|
32449
|
+
strokeWidth: 0.02,
|
|
32450
|
+
fill: "none",
|
|
32451
|
+
className: className
|
|
32452
|
+
}));
|
|
32453
|
+
};
|
|
32454
|
+
const isRightPolygonAngle = angle => Math.abs(angle - Math.PI / 2) < 0.01;
|
|
32455
|
+
const isRightAngle = angle => Math.round(angle) === 90;
|
|
32456
|
+
|
|
32457
|
+
/**
|
|
32458
|
+
* Determines if an angle is an inside (false) or outside (true) angle.
|
|
32459
|
+
* They way, we know to flip the `largeArc` and `sweepArc` flags.
|
|
32460
|
+
* Uses the priciple that a ray from a point inside a polygon will intersect
|
|
32461
|
+
* with an odd number of lines, while a ray from a point outside the polygon
|
|
32462
|
+
* will intersect with an even number of lines.
|
|
32463
|
+
* https://stackoverflow.com/questions/217578/how-can-i-determine-whether-a-2d-point-is-within-a-polygon
|
|
32464
|
+
*/
|
|
32465
|
+
const shouldDrawArcOutside = (midpoint, vertex, range, polygonLines) => {
|
|
32466
|
+
// Create a ray from the midpoint (inside angle) to the edge of the range
|
|
32467
|
+
const rangeIntersectionPoint = getIntersectionOfRayWithBox(midpoint, vertex, range);
|
|
32468
|
+
let lineIntersectionCount = 0;
|
|
32469
|
+
polygonLines.forEach(line => segmentsIntersect([vertex, rangeIntersectionPoint], line) && lineIntersectionCount++);
|
|
32470
|
+
|
|
32471
|
+
// If the number of intersections is even, the angle is inside the polygon
|
|
32472
|
+
return !isEven(lineIntersectionCount);
|
|
32473
|
+
};
|
|
32474
|
+
const isEven = n => n % 2 === 0;
|
|
32475
|
+
|
|
32476
|
+
// This function calculates the bisector point of an angle formed by two points
|
|
32477
|
+
// and a vertex. It is used to position the angle label so that it is always
|
|
32478
|
+
// outside the arc at the exact midpoint of the angle.
|
|
32479
|
+
// Reflex angles make use of polar coordinates to determine the correct direction
|
|
32480
|
+
function calculateBisectorPoint(point1, point2, vertex, isReflex, allowReflex, arcRadius) {
|
|
32481
|
+
const [originX, originY] = vertex;
|
|
32482
|
+
const [x1, y1] = point1;
|
|
32483
|
+
const [x2, y2] = point2;
|
|
32484
|
+
|
|
32485
|
+
// Convert the Cartesian Coordinates to vectors
|
|
32486
|
+
const vectorA = [x1 - originX, y1 - originY];
|
|
32487
|
+
const vectorB = [x2 - originX, y2 - originY];
|
|
32488
|
+
|
|
32489
|
+
// Calculate the average angle of the vectors
|
|
32490
|
+
// so that we can point the bisector in the correct direction using polar coordinates
|
|
32491
|
+
const angleA = Math.atan2(vectorA[1], vectorA[0]);
|
|
32492
|
+
const angleB = Math.atan2(vectorB[1], vectorB[0]);
|
|
32493
|
+
|
|
32494
|
+
// Calculate the average of these two angles
|
|
32495
|
+
let averageAngle = (angleA + angleB) / 2;
|
|
32496
|
+
const angleRadians = Math.abs(angleA - angleB);
|
|
32497
|
+
|
|
32498
|
+
// Adjust the average angle to point in the correct direction
|
|
32499
|
+
// and to account for reflex angles and a bug with 180 degrees
|
|
32500
|
+
// that occurs due to our angleOffsetDegrees option in the graph
|
|
32501
|
+
if (allowReflex) {
|
|
32502
|
+
// If the resulting angles are less than 180 degrees,
|
|
32503
|
+
// or if the user has flipped the points on the interactive element
|
|
32504
|
+
// ensure that we have the correct direction for the reflex angle
|
|
32505
|
+
if (angleRadians <= Math.PI && isReflex || angleB > angleA) {
|
|
32506
|
+
averageAngle += Math.PI; // Add 180 degrees
|
|
32507
|
+
}
|
|
32508
|
+
} else {
|
|
32509
|
+
// If the resulting angles are greater than 180 degrees, adjust
|
|
32510
|
+
// to get the correct angle, as we already know that the angle is not reflexive
|
|
32511
|
+
// This fixes a bug that occurs at 180 degrees due to our angleOffsetDegrees option in the graph
|
|
32512
|
+
if (angleRadians > Math.PI) {
|
|
32513
|
+
averageAngle -= Math.PI; // Subract 180 degrees
|
|
32514
|
+
}
|
|
32515
|
+
}
|
|
32516
|
+
|
|
32517
|
+
// Convert the average angle back to Cartesian coordinates
|
|
32518
|
+
const sum = [Math.cos(averageAngle), Math.sin(averageAngle)];
|
|
32519
|
+
|
|
32520
|
+
// Calculate the magnitude of the sum to normalize it
|
|
32521
|
+
const sumMagnitude = Math.sqrt(sum[0] ** 2 + sum[1] ** 2);
|
|
32522
|
+
const bisectorDirection = [sum[0] / sumMagnitude, sum[1] / sumMagnitude];
|
|
32523
|
+
|
|
32524
|
+
// Calculate the initial distance of the bisector direction from the origin
|
|
32525
|
+
const initialDistance = Math.sqrt(bisectorDirection[0] ** 2 + bisectorDirection[1] ** 2);
|
|
32526
|
+
|
|
32527
|
+
// Determine the minimum radius to ensure that the text is always outside the arc
|
|
32528
|
+
const requiredDistance = arcRadius * 1.75;
|
|
32529
|
+
let radius = requiredDistance / initialDistance;
|
|
32530
|
+
|
|
32531
|
+
// Apply radius only if the initial distance is less than required
|
|
32532
|
+
if (initialDistance >= requiredDistance) {
|
|
32533
|
+
radius = 1; // Use the unit vector as is
|
|
32534
|
+
}
|
|
32535
|
+
|
|
32536
|
+
// Scale the bisector direction by the radius
|
|
32537
|
+
const bisectorPoint = [bisectorDirection[0] * radius, bisectorDirection[1] * radius];
|
|
32538
|
+
|
|
32539
|
+
// Add the vertex to the bisector point to get the final position
|
|
32540
|
+
// to ensure that the angle label moves with the interactive element
|
|
32541
|
+
const scaledBisector = vec.add(bisectorPoint, vertex);
|
|
32542
|
+
return scaledBisector;
|
|
32543
|
+
}
|
|
32544
|
+
|
|
32236
32545
|
/**
|
|
32237
32546
|
* 44 is touch best practice and AAA compliant for WCAG
|
|
32238
32547
|
* https://www.w3.org/WAI/WCAG21/Understanding/target-size.html
|
|
32239
32548
|
*/
|
|
32240
32549
|
const TARGET_SIZE = 44;
|
|
32550
|
+
const REMOVE_BUTTON_ID = "perseus_mafs_remove_button";
|
|
32241
32551
|
|
|
32242
32552
|
// same as pointsFromNormalized in interactive-graph.tsx
|
|
32243
32553
|
const normalizePoints = (range, step, coordsList, noSnap) => coordsList.map(coords =>
|
|
@@ -32268,6 +32578,9 @@ function bound$1({
|
|
|
32268
32578
|
const boundingBox = inset(snapStep, range);
|
|
32269
32579
|
return clampToBox(boundingBox, point);
|
|
32270
32580
|
}
|
|
32581
|
+
function isUnlimitedGraphState(state) {
|
|
32582
|
+
return state.type === "point" && state.numPoints === "unlimited" || state.type === "polygon" && state.numSides === "unlimited";
|
|
32583
|
+
}
|
|
32271
32584
|
|
|
32272
32585
|
var isProduction = process.env.NODE_ENV === 'production';
|
|
32273
32586
|
var prefix = 'Invariant failed';
|
|
@@ -32434,6 +32747,14 @@ function range(min, max, step = 1) {
|
|
|
32434
32747
|
return result;
|
|
32435
32748
|
}
|
|
32436
32749
|
|
|
32750
|
+
function srFormatNumber(a, locale) {
|
|
32751
|
+
// adding zero here converts negative zero to positive zero.
|
|
32752
|
+
return (0 + a).toLocaleString(locale, {
|
|
32753
|
+
maximumFractionDigits: 3,
|
|
32754
|
+
useGrouping: false // no thousands separators
|
|
32755
|
+
});
|
|
32756
|
+
}
|
|
32757
|
+
|
|
32437
32758
|
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
32438
32759
|
// graph.
|
|
32439
32760
|
const hitboxSizePx = 48;
|
|
@@ -32441,33 +32762,26 @@ const hitboxSizePx = 48;
|
|
|
32441
32762
|
// MovablePointView is a purely presentational component (i.e. it is a pure
|
|
32442
32763
|
// function with no state or effects) that renders the SVG for a movable point
|
|
32443
32764
|
// on an interactive graph.
|
|
32444
|
-
//
|
|
32445
|
-
// It has two modes for managing tabbing / focus: "controlled" (where the caller
|
|
32446
|
-
// manages the display of the focus ring, and the point itself cannot be
|
|
32447
|
-
// focused) and "uncontrolled" (where the point is focusable, and the browser
|
|
32448
|
-
// manages the focus state and styling). For context on why we did this, see
|
|
32449
|
-
// the description of https://github.com/Khan/perseus/pull/1240
|
|
32450
32765
|
const MovablePointView = /*#__PURE__*/forwardRef((props, hitboxRef) => {
|
|
32451
32766
|
var _Object$entries$find$, _Object$entries$find;
|
|
32452
32767
|
const {
|
|
32453
32768
|
range,
|
|
32454
32769
|
markings,
|
|
32455
|
-
showTooltips
|
|
32456
|
-
disableKeyboardInteraction
|
|
32770
|
+
showTooltips
|
|
32457
32771
|
} = useGraphConfig();
|
|
32458
32772
|
const {
|
|
32459
32773
|
point,
|
|
32460
32774
|
color: color$1 = color.blue,
|
|
32461
32775
|
dragging,
|
|
32462
|
-
focusBehavior,
|
|
32463
32776
|
cursor,
|
|
32777
|
+
showFocusRing,
|
|
32464
32778
|
onClick = () => {}
|
|
32465
32779
|
} = props;
|
|
32466
32780
|
|
|
32467
32781
|
// WB Tooltip requires a color name for the background color.
|
|
32468
32782
|
// Since the color in props is a hex value, a reverse lookup is needed.
|
|
32469
32783
|
const wbColorName = (_Object$entries$find$ = (_Object$entries$find = Object.entries(color).find(([_, value]) => value === color$1)) == null ? void 0 : _Object$entries$find[0]) != null ? _Object$entries$find$ : "blue";
|
|
32470
|
-
const pointClasses =
|
|
32784
|
+
const pointClasses = classNames("movable-point", dragging && "movable-point--dragging", showFocusRing && "movable-point--focus");
|
|
32471
32785
|
const [[x, y]] = useTransformVectorsToPixels(point);
|
|
32472
32786
|
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
32473
32787
|
const [[verticalStartX]] = useTransformVectorsToPixels([xMin, 0]);
|
|
@@ -32496,15 +32810,6 @@ const MovablePointView = /*#__PURE__*/forwardRef((props, hitboxRef) => {
|
|
|
32496
32810
|
cursor
|
|
32497
32811
|
},
|
|
32498
32812
|
"data-testid": "movable-point",
|
|
32499
|
-
tabIndex: disableKeyboardInteraction ? -1 : tabIndex(focusBehavior),
|
|
32500
|
-
onFocus: event => {
|
|
32501
|
-
const callback = getOnFocusChangeCallback(focusBehavior);
|
|
32502
|
-
callback && callback(event, true);
|
|
32503
|
-
},
|
|
32504
|
-
onBlur: event => {
|
|
32505
|
-
const callback = getOnFocusChangeCallback(focusBehavior);
|
|
32506
|
-
callback && callback(event, false);
|
|
32507
|
-
},
|
|
32508
32813
|
onClick: onClick
|
|
32509
32814
|
}, /*#__PURE__*/React.createElement("circle", {
|
|
32510
32815
|
className: "movable-point-hitbox",
|
|
@@ -32541,25 +32846,113 @@ const MovablePointView = /*#__PURE__*/forwardRef((props, hitboxRef) => {
|
|
|
32541
32846
|
}
|
|
32542
32847
|
}, svgForPoint) : svgForPoint);
|
|
32543
32848
|
});
|
|
32544
|
-
|
|
32545
|
-
|
|
32546
|
-
|
|
32547
|
-
|
|
32548
|
-
return "";
|
|
32849
|
+
|
|
32850
|
+
// TODO(benchristel): Move this to a more central location if it's reused.
|
|
32851
|
+
// Or install the library.
|
|
32852
|
+
function classNames(...names) {
|
|
32853
|
+
return names.filter(Boolean).join(" ");
|
|
32549
32854
|
}
|
|
32550
|
-
|
|
32551
|
-
|
|
32552
|
-
|
|
32553
|
-
|
|
32554
|
-
|
|
32855
|
+
|
|
32856
|
+
function useControlPoint(params) {
|
|
32857
|
+
const {
|
|
32858
|
+
snapStep,
|
|
32859
|
+
disableKeyboardInteraction
|
|
32860
|
+
} = useGraphConfig();
|
|
32861
|
+
const {
|
|
32862
|
+
point,
|
|
32863
|
+
color,
|
|
32864
|
+
cursor,
|
|
32865
|
+
constrain = p => snap(snapStep, p),
|
|
32866
|
+
onMove = noop$1,
|
|
32867
|
+
onClick = noop$1,
|
|
32868
|
+
onFocus = noop$1,
|
|
32869
|
+
onBlur = noop$1,
|
|
32870
|
+
forwardedRef = noop$1
|
|
32871
|
+
} = params;
|
|
32872
|
+
const {
|
|
32873
|
+
strings,
|
|
32874
|
+
locale
|
|
32875
|
+
} = usePerseusI18n();
|
|
32876
|
+
const [focused, setFocused] = useState(false);
|
|
32877
|
+
const focusableHandleRef = useRef(null);
|
|
32878
|
+
useDraggable({
|
|
32879
|
+
gestureTarget: focusableHandleRef,
|
|
32880
|
+
point,
|
|
32881
|
+
onMove,
|
|
32882
|
+
constrainKeyboardMovement: constrain
|
|
32883
|
+
});
|
|
32884
|
+
const visiblePointRef = useRef(null);
|
|
32885
|
+
const {
|
|
32886
|
+
dragging
|
|
32887
|
+
} = useDraggable({
|
|
32888
|
+
gestureTarget: visiblePointRef,
|
|
32889
|
+
point,
|
|
32890
|
+
onMove,
|
|
32891
|
+
constrainKeyboardMovement: constrain
|
|
32892
|
+
});
|
|
32893
|
+
useLayoutEffect(() => {
|
|
32894
|
+
setForwardedRef(forwardedRef, focusableHandleRef.current);
|
|
32895
|
+
}, [forwardedRef]);
|
|
32896
|
+
const focusableHandle = /*#__PURE__*/React.createElement("g", {
|
|
32897
|
+
"data-testid": "movable-point__focusable-handle",
|
|
32898
|
+
className: "movable-point__focusable-handle",
|
|
32899
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
32900
|
+
ref: focusableHandleRef,
|
|
32901
|
+
role: "button",
|
|
32902
|
+
"aria-label": strings.srPointAtCoordinates({
|
|
32903
|
+
x: srFormatNumber(point[X], locale),
|
|
32904
|
+
y: srFormatNumber(point[Y], locale)
|
|
32905
|
+
})
|
|
32906
|
+
// aria-live="assertive" causes the new location of the point to be
|
|
32907
|
+
// announced immediately on move.
|
|
32908
|
+
,
|
|
32909
|
+
"aria-live": "assertive",
|
|
32910
|
+
onFocus: event => {
|
|
32911
|
+
onFocus(event);
|
|
32912
|
+
setFocused(true);
|
|
32913
|
+
},
|
|
32914
|
+
onBlur: event => {
|
|
32915
|
+
onBlur(event);
|
|
32916
|
+
setFocused(false);
|
|
32917
|
+
}
|
|
32918
|
+
});
|
|
32919
|
+
const visiblePoint = /*#__PURE__*/React.createElement(MovablePointView, {
|
|
32920
|
+
cursor: cursor,
|
|
32921
|
+
onClick: () => {
|
|
32922
|
+
var _focusableHandleRef$c;
|
|
32923
|
+
onClick();
|
|
32924
|
+
(_focusableHandleRef$c = focusableHandleRef.current) == null || _focusableHandleRef$c.focus();
|
|
32925
|
+
},
|
|
32926
|
+
point: point,
|
|
32927
|
+
dragging: dragging,
|
|
32928
|
+
color: color,
|
|
32929
|
+
ref: visiblePointRef,
|
|
32930
|
+
showFocusRing: focused
|
|
32931
|
+
});
|
|
32932
|
+
return {
|
|
32933
|
+
focusableHandle,
|
|
32934
|
+
visiblePoint,
|
|
32935
|
+
focusableHandleRef,
|
|
32936
|
+
visiblePointRef
|
|
32937
|
+
};
|
|
32555
32938
|
}
|
|
32556
|
-
|
|
32557
|
-
|
|
32558
|
-
|
|
32939
|
+
|
|
32940
|
+
// TODO(benchristel): move this to a more central place if we want to reuse it.
|
|
32941
|
+
function setForwardedRef(ref, value) {
|
|
32942
|
+
if (typeof ref === "function") {
|
|
32943
|
+
ref(value);
|
|
32944
|
+
} else if (ref !== null) {
|
|
32945
|
+
ref.current = value;
|
|
32559
32946
|
}
|
|
32560
|
-
return () => {};
|
|
32561
32947
|
}
|
|
32562
32948
|
|
|
32949
|
+
// This `noop` const is an optimization. Above, we use the forwardedRef
|
|
32950
|
+
// variable, which defaults to `noop`, in a useEffect deps array. Using `noop`
|
|
32951
|
+
// as the default value instead of `() => {}` ensures that the forwardedRef
|
|
32952
|
+
// variable will have the same value on repeated renders, preventing the
|
|
32953
|
+
// useEffect callback from re-running needlessly.
|
|
32954
|
+
const noop$1 = () => {};
|
|
32955
|
+
|
|
32563
32956
|
const MovableLine = props => {
|
|
32564
32957
|
const {
|
|
32565
32958
|
onMoveLine = () => {},
|
|
@@ -32583,11 +32976,19 @@ const MovableLine = props => {
|
|
|
32583
32976
|
const {
|
|
32584
32977
|
visiblePoint: visiblePoint1,
|
|
32585
32978
|
focusableHandle: focusableHandle1
|
|
32586
|
-
} = useControlPoint(
|
|
32979
|
+
} = useControlPoint({
|
|
32980
|
+
point: start,
|
|
32981
|
+
color,
|
|
32982
|
+
onMove: p => onMovePoint(0, p)
|
|
32983
|
+
});
|
|
32587
32984
|
const {
|
|
32588
32985
|
visiblePoint: visiblePoint2,
|
|
32589
32986
|
focusableHandle: focusableHandle2
|
|
32590
|
-
} = useControlPoint(
|
|
32987
|
+
} = useControlPoint({
|
|
32988
|
+
point: end,
|
|
32989
|
+
color,
|
|
32990
|
+
onMove: p => onMovePoint(1, p)
|
|
32991
|
+
});
|
|
32591
32992
|
const line = /*#__PURE__*/React.createElement(Line$1, {
|
|
32592
32993
|
start: start,
|
|
32593
32994
|
end: end,
|
|
@@ -32597,51 +32998,6 @@ const MovableLine = props => {
|
|
|
32597
32998
|
});
|
|
32598
32999
|
return /*#__PURE__*/React.createElement(React.Fragment, null, focusableHandle1, line, focusableHandle2, visiblePoint1, visiblePoint2);
|
|
32599
33000
|
};
|
|
32600
|
-
function useControlPoint(point, color, onMovePoint) {
|
|
32601
|
-
const {
|
|
32602
|
-
snapStep,
|
|
32603
|
-
disableKeyboardInteraction
|
|
32604
|
-
} = useGraphConfig();
|
|
32605
|
-
const [focused, setFocused] = useState(false);
|
|
32606
|
-
const keyboardHandleRef = useRef(null);
|
|
32607
|
-
useDraggable({
|
|
32608
|
-
gestureTarget: keyboardHandleRef,
|
|
32609
|
-
point,
|
|
32610
|
-
onMove: onMovePoint,
|
|
32611
|
-
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
32612
|
-
});
|
|
32613
|
-
const visiblePointRef = useRef(null);
|
|
32614
|
-
const {
|
|
32615
|
-
dragging
|
|
32616
|
-
} = useDraggable({
|
|
32617
|
-
gestureTarget: visiblePointRef,
|
|
32618
|
-
point,
|
|
32619
|
-
onMove: onMovePoint,
|
|
32620
|
-
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
32621
|
-
});
|
|
32622
|
-
const focusableHandle = /*#__PURE__*/React.createElement("g", {
|
|
32623
|
-
"data-testid": "movable-point__focusable-handle",
|
|
32624
|
-
className: "movable-point__focusable-handle",
|
|
32625
|
-
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
32626
|
-
ref: keyboardHandleRef,
|
|
32627
|
-
onFocus: () => setFocused(true),
|
|
32628
|
-
onBlur: () => setFocused(false)
|
|
32629
|
-
});
|
|
32630
|
-
const visiblePoint = /*#__PURE__*/React.createElement(MovablePointView, {
|
|
32631
|
-
point: point,
|
|
32632
|
-
dragging: dragging,
|
|
32633
|
-
color: color,
|
|
32634
|
-
ref: visiblePointRef,
|
|
32635
|
-
focusBehavior: {
|
|
32636
|
-
type: "controlled",
|
|
32637
|
-
showFocusRing: focused
|
|
32638
|
-
}
|
|
32639
|
-
});
|
|
32640
|
-
return {
|
|
32641
|
-
focusableHandle,
|
|
32642
|
-
visiblePoint
|
|
32643
|
-
};
|
|
32644
|
-
}
|
|
32645
33001
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
32646
33002
|
const Line$1 = props => {
|
|
32647
33003
|
const {
|
|
@@ -32731,25 +33087,338 @@ function trimRange(range, graphDimensionsInPixels) {
|
|
|
32731
33087
|
return inset([graphUnitsToTrimX, graphUnitsToTrimY], range);
|
|
32732
33088
|
}
|
|
32733
33089
|
|
|
32734
|
-
const
|
|
33090
|
+
const MovablePoint$1 = /*#__PURE__*/React.forwardRef((props, pointRef) => {
|
|
32735
33091
|
const {
|
|
32736
|
-
|
|
33092
|
+
visiblePoint,
|
|
33093
|
+
focusableHandle
|
|
33094
|
+
} = useControlPoint(_extends({}, props, {
|
|
33095
|
+
forwardedRef: pointRef
|
|
33096
|
+
}));
|
|
33097
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, focusableHandle, visiblePoint);
|
|
33098
|
+
});
|
|
33099
|
+
|
|
33100
|
+
function renderAngleGraph(state, dispatch) {
|
|
33101
|
+
return {
|
|
33102
|
+
graph: /*#__PURE__*/React.createElement(AngleGraph, {
|
|
33103
|
+
graphState: state,
|
|
33104
|
+
dispatch: dispatch
|
|
33105
|
+
}),
|
|
33106
|
+
interactiveElementsDescription: null
|
|
33107
|
+
};
|
|
33108
|
+
}
|
|
33109
|
+
function AngleGraph(props) {
|
|
33110
|
+
const {
|
|
33111
|
+
dispatch,
|
|
33112
|
+
graphState
|
|
32737
33113
|
} = props;
|
|
32738
33114
|
const {
|
|
32739
|
-
|
|
32740
|
-
} =
|
|
32741
|
-
|
|
32742
|
-
|
|
32743
|
-
|
|
32744
|
-
|
|
32745
|
-
|
|
32746
|
-
|
|
32747
|
-
|
|
32748
|
-
|
|
33115
|
+
graphDimensionsInPixels
|
|
33116
|
+
} = useGraphConfig();
|
|
33117
|
+
const {
|
|
33118
|
+
coords,
|
|
33119
|
+
showAngles,
|
|
33120
|
+
range,
|
|
33121
|
+
allowReflexAngles,
|
|
33122
|
+
snapDegrees
|
|
33123
|
+
} = graphState;
|
|
33124
|
+
|
|
33125
|
+
// Break the coords into the two end points and the center point
|
|
33126
|
+
const endPoints = [coords[0], coords[2]];
|
|
33127
|
+
const centerPoint = coords[1];
|
|
33128
|
+
|
|
33129
|
+
// Convert the vectors to pixels for rendering the svg lines
|
|
33130
|
+
const angleLines = [[centerPoint, endPoints[0]], [centerPoint, endPoints[1]]];
|
|
33131
|
+
const linePixelCoords = [useTransformVectorsToPixels(centerPoint, endPoints[0]), useTransformVectorsToPixels(centerPoint, endPoints[1])];
|
|
33132
|
+
|
|
33133
|
+
// Create the SVG lines for the angle
|
|
33134
|
+
const svgLines = linePixelCoords.map(([startPtPx, endPtPx], i) => {
|
|
33135
|
+
const trimmedRange = trimRange(range, graphDimensionsInPixels);
|
|
33136
|
+
const endExtend = getIntersectionOfRayWithBox(angleLines[i][0], angleLines[i][1], trimmedRange);
|
|
33137
|
+
return /*#__PURE__*/React.createElement("g", {
|
|
33138
|
+
key: `line-${i}`
|
|
33139
|
+
}, /*#__PURE__*/React.createElement(SVGLine, {
|
|
33140
|
+
start: startPtPx,
|
|
33141
|
+
end: endPtPx,
|
|
33142
|
+
style: {
|
|
33143
|
+
stroke: "var(--movable-line-stroke-color)",
|
|
33144
|
+
strokeWidth: "var(--movable-line-stroke-weight)"
|
|
33145
|
+
}
|
|
33146
|
+
}), /*#__PURE__*/React.createElement(Vector, {
|
|
33147
|
+
tail: angleLines[i][1],
|
|
33148
|
+
tip: endExtend,
|
|
33149
|
+
color: "var(--movable-line-stroke-color)"
|
|
33150
|
+
}));
|
|
33151
|
+
});
|
|
33152
|
+
|
|
33153
|
+
// Create the angle indicator parameters
|
|
33154
|
+
const angleParams = {
|
|
33155
|
+
vertex: centerPoint,
|
|
33156
|
+
coords: endPoints,
|
|
33157
|
+
allowReflexAngles: allowReflexAngles || false,
|
|
33158
|
+
// Whether to allow reflex angles or not
|
|
33159
|
+
snapDegrees: snapDegrees || 1,
|
|
33160
|
+
// The multiple of degrees to snap to
|
|
33161
|
+
range: range,
|
|
33162
|
+
showAngles: showAngles || false // Whether to show the angle or not
|
|
33163
|
+
};
|
|
33164
|
+
|
|
33165
|
+
// Render the lines, angle, and then movable points
|
|
33166
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, svgLines, /*#__PURE__*/React.createElement(Angle, angleParams), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33167
|
+
point: coords[1],
|
|
33168
|
+
constrain: p => p,
|
|
33169
|
+
onMove: destination => dispatch(actions.angle.movePoint(1, destination))
|
|
33170
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33171
|
+
point: coords[0],
|
|
33172
|
+
constrain: getAngleSideConstraint(coords[0], coords[1], snapDegrees || 1),
|
|
33173
|
+
onMove: destination => dispatch(actions.angle.movePoint(0, destination))
|
|
33174
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33175
|
+
point: coords[2],
|
|
33176
|
+
constrain: getAngleSideConstraint(coords[2], coords[1], snapDegrees || 1),
|
|
33177
|
+
onMove: destination => dispatch(actions.angle.movePoint(2, destination))
|
|
33178
|
+
}));
|
|
33179
|
+
}
|
|
33180
|
+
const positiveX = [1, 0];
|
|
33181
|
+
const negativeX = [-1, 0];
|
|
33182
|
+
const positiveY = [0, 1];
|
|
33183
|
+
const negativeY = [0, -1];
|
|
33184
|
+
function getAngleSideConstraint(sidePoint, vertex, snapDegrees) {
|
|
33185
|
+
var _findIntersectionOfRa, _findIntersectionOfRa2, _findIntersectionOfRa3, _findIntersectionOfRa4;
|
|
33186
|
+
const currentAngle = calculateAngleInDegrees(vec.sub(sidePoint, vertex));
|
|
33187
|
+
|
|
33188
|
+
// Find the rays that start at the current point and point up, down, left
|
|
33189
|
+
// and right.
|
|
33190
|
+
const leftRay = [sidePoint, vec.add(sidePoint, negativeX)];
|
|
33191
|
+
const rightRay = [sidePoint, vec.add(sidePoint, positiveX)];
|
|
33192
|
+
const upRay = [sidePoint, vec.add(sidePoint, positiveY)];
|
|
33193
|
+
const downRay = [sidePoint, vec.add(sidePoint, negativeY)];
|
|
33194
|
+
|
|
33195
|
+
// find the angles that lie one snap step clockwise and counter-clockwise
|
|
33196
|
+
// from the current angle. These are the angles to which the side can be
|
|
33197
|
+
// moved.
|
|
33198
|
+
const oneStepCounterClockwise = currentAngle + snapDegrees;
|
|
33199
|
+
const oneStepClockwise = currentAngle - snapDegrees;
|
|
33200
|
+
|
|
33201
|
+
// find the rays that start from the vertex and point in the direction of
|
|
33202
|
+
// the angles we just computed.
|
|
33203
|
+
const counterClockwiseRay = [vertex, vec.add(vertex, polar(1, oneStepCounterClockwise))];
|
|
33204
|
+
const clockwiseRay = [vertex, vec.add(vertex, polar(1, oneStepClockwise))];
|
|
33205
|
+
|
|
33206
|
+
// find the intersections of those rays with the horizontal and vertical
|
|
33207
|
+
// rays extending from the sidePoint. These intersections are the points to
|
|
33208
|
+
// which sidePoint can move that will result in a rotation of `snapDegrees`.
|
|
33209
|
+
const left = (_findIntersectionOfRa = findIntersectionOfRays(leftRay, counterClockwiseRay)) != null ? _findIntersectionOfRa : findIntersectionOfRays(leftRay, clockwiseRay);
|
|
33210
|
+
const right = (_findIntersectionOfRa2 = findIntersectionOfRays(rightRay, counterClockwiseRay)) != null ? _findIntersectionOfRa2 : findIntersectionOfRays(rightRay, clockwiseRay);
|
|
33211
|
+
const up = (_findIntersectionOfRa3 = findIntersectionOfRays(upRay, counterClockwiseRay)) != null ? _findIntersectionOfRa3 : findIntersectionOfRays(upRay, clockwiseRay);
|
|
33212
|
+
const down = (_findIntersectionOfRa4 = findIntersectionOfRays(downRay, counterClockwiseRay)) != null ? _findIntersectionOfRa4 : findIntersectionOfRays(downRay, clockwiseRay);
|
|
33213
|
+
return {
|
|
33214
|
+
up: up != null ? up : sidePoint,
|
|
33215
|
+
down: down != null ? down : sidePoint,
|
|
33216
|
+
left: left != null ? left : sidePoint,
|
|
33217
|
+
right: right != null ? right : sidePoint
|
|
33218
|
+
};
|
|
33219
|
+
}
|
|
33220
|
+
|
|
33221
|
+
function getGradableGraph(state, initialGraph) {
|
|
33222
|
+
if (!state.hasBeenInteractedWith) {
|
|
33223
|
+
return _extends({}, initialGraph);
|
|
33224
|
+
}
|
|
33225
|
+
if (initialGraph.type === "linear-system" && state.type === "linear-system") {
|
|
33226
|
+
return _extends({}, initialGraph, {
|
|
33227
|
+
coords: state.coords
|
|
33228
|
+
});
|
|
33229
|
+
}
|
|
33230
|
+
if (state.type === "segment" && initialGraph.type === "segment") {
|
|
33231
|
+
return _extends({}, initialGraph, {
|
|
33232
|
+
coords: state.coords
|
|
33233
|
+
});
|
|
33234
|
+
}
|
|
33235
|
+
if (state.type === "linear" && initialGraph.type === "linear") {
|
|
33236
|
+
return _extends({}, initialGraph, {
|
|
33237
|
+
coords: state.coords
|
|
33238
|
+
});
|
|
33239
|
+
}
|
|
33240
|
+
if (state.type === "ray" && initialGraph.type === "ray") {
|
|
33241
|
+
return _extends({}, initialGraph, {
|
|
33242
|
+
coords: state.coords
|
|
33243
|
+
});
|
|
33244
|
+
}
|
|
33245
|
+
if (state.type === "polygon" && initialGraph.type === "polygon") {
|
|
33246
|
+
return _extends({}, initialGraph, {
|
|
33247
|
+
coords: state.coords
|
|
33248
|
+
});
|
|
33249
|
+
}
|
|
33250
|
+
if (state.type === "point" && initialGraph.type === "point") {
|
|
33251
|
+
return _extends({}, initialGraph, {
|
|
33252
|
+
coords: state.coords
|
|
33253
|
+
});
|
|
33254
|
+
}
|
|
33255
|
+
if (state.type === "circle" && initialGraph.type === "circle") {
|
|
33256
|
+
return _extends({}, initialGraph, {
|
|
33257
|
+
center: state.center,
|
|
33258
|
+
radius: getRadius(state)
|
|
33259
|
+
});
|
|
33260
|
+
}
|
|
33261
|
+
if (state.type === "quadratic" && initialGraph.type === "quadratic") {
|
|
33262
|
+
return _extends({}, initialGraph, {
|
|
33263
|
+
coords: state.coords
|
|
33264
|
+
});
|
|
33265
|
+
}
|
|
33266
|
+
if (state.type === "sinusoid" && initialGraph.type === "sinusoid") {
|
|
33267
|
+
return _extends({}, initialGraph, {
|
|
33268
|
+
coords: state.coords
|
|
33269
|
+
});
|
|
33270
|
+
}
|
|
33271
|
+
if (state.type === "angle" && initialGraph.type === "angle") {
|
|
33272
|
+
// We're going to reverse the coords for scoring if the angle is clockwise and
|
|
33273
|
+
// we don't allow reflex angles. This is because the angle is largely defined
|
|
33274
|
+
// by the order of the points in the coords array, and we want to maintain
|
|
33275
|
+
// the same angle scoring with the legacy graph (which had a bug).
|
|
33276
|
+
// (LEMS-2190): When we remove the legacy graph, move this logic to the scoring function.
|
|
33277
|
+
const areClockwise = clockwise$1([state.coords[0], state.coords[2], state.coords[1]]);
|
|
33278
|
+
const shouldReverseCoords = areClockwise && !state.allowReflexAngles;
|
|
33279
|
+
const coords = shouldReverseCoords ? state.coords.slice().reverse() : state.coords;
|
|
33280
|
+
return _extends({}, initialGraph, {
|
|
33281
|
+
coords,
|
|
33282
|
+
allowReflexAngles: state.allowReflexAngles
|
|
33283
|
+
});
|
|
33284
|
+
}
|
|
33285
|
+
if (state.type === "none" && initialGraph.type === "none") {
|
|
33286
|
+
return {
|
|
33287
|
+
type: "none"
|
|
33288
|
+
};
|
|
33289
|
+
}
|
|
33290
|
+
throw new Error("Mafs is not yet implemented for graph type: " + initialGraph.type);
|
|
33291
|
+
}
|
|
33292
|
+
|
|
33293
|
+
/**
|
|
33294
|
+
* determine radius of a circle graph
|
|
33295
|
+
*
|
|
33296
|
+
* @param graph - the graph object containing the circle
|
|
33297
|
+
* @returns the radius of the circle
|
|
33298
|
+
*/
|
|
33299
|
+
function getRadius(graph) {
|
|
33300
|
+
const [centerX, centerY] = graph.center;
|
|
33301
|
+
const [edgeX, edgeY] = graph.radiusPoint;
|
|
33302
|
+
return Math.sqrt(Math.pow(edgeX - centerX, 2) + Math.pow(edgeY - centerY, 2));
|
|
33303
|
+
}
|
|
33304
|
+
|
|
33305
|
+
function renderCircleGraph(state, dispatch) {
|
|
33306
|
+
return {
|
|
33307
|
+
graph: /*#__PURE__*/React.createElement(CircleGraph, {
|
|
33308
|
+
graphState: state,
|
|
33309
|
+
dispatch: dispatch
|
|
33310
|
+
}),
|
|
33311
|
+
interactiveElementsDescription: null
|
|
33312
|
+
};
|
|
33313
|
+
}
|
|
33314
|
+
function CircleGraph(props) {
|
|
33315
|
+
const {
|
|
33316
|
+
dispatch,
|
|
33317
|
+
graphState
|
|
33318
|
+
} = props;
|
|
33319
|
+
const {
|
|
33320
|
+
center,
|
|
33321
|
+
radiusPoint
|
|
33322
|
+
} = graphState;
|
|
33323
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(MovableCircle, {
|
|
33324
|
+
center: center,
|
|
33325
|
+
radius: getRadius(graphState),
|
|
33326
|
+
onMove: c => dispatch(actions.circle.moveCenter(c))
|
|
33327
|
+
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33328
|
+
point: radiusPoint,
|
|
33329
|
+
cursor: "ew-resize",
|
|
33330
|
+
onMove: newRadiusPoint => {
|
|
33331
|
+
dispatch(actions.circle.moveRadiusPoint(newRadiusPoint));
|
|
32749
33332
|
}
|
|
32750
|
-
}))
|
|
32751
|
-
}
|
|
33333
|
+
}));
|
|
33334
|
+
}
|
|
33335
|
+
function MovableCircle(props) {
|
|
33336
|
+
const {
|
|
33337
|
+
center,
|
|
33338
|
+
radius,
|
|
33339
|
+
onMove
|
|
33340
|
+
} = props;
|
|
33341
|
+
const {
|
|
33342
|
+
snapStep,
|
|
33343
|
+
disableKeyboardInteraction
|
|
33344
|
+
} = useGraphConfig();
|
|
33345
|
+
const draggableRef = useRef(null);
|
|
33346
|
+
const {
|
|
33347
|
+
dragging
|
|
33348
|
+
} = useDraggable({
|
|
33349
|
+
gestureTarget: draggableRef,
|
|
33350
|
+
point: center,
|
|
33351
|
+
onMove,
|
|
33352
|
+
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
33353
|
+
});
|
|
33354
|
+
const [centerPx] = useTransformVectorsToPixels(center);
|
|
33355
|
+
const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
|
|
33356
|
+
return /*#__PURE__*/React.createElement("g", {
|
|
33357
|
+
ref: draggableRef,
|
|
33358
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
33359
|
+
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
|
|
33360
|
+
}, /*#__PURE__*/React.createElement("ellipse", {
|
|
33361
|
+
className: "focus-ring",
|
|
33362
|
+
cx: centerPx[X],
|
|
33363
|
+
cy: centerPx[Y],
|
|
33364
|
+
rx: radiiPx[X] + 3,
|
|
33365
|
+
ry: radiiPx[Y] + 3
|
|
33366
|
+
}), /*#__PURE__*/React.createElement("ellipse", {
|
|
33367
|
+
className: "circle",
|
|
33368
|
+
cx: centerPx[X],
|
|
33369
|
+
cy: centerPx[Y],
|
|
33370
|
+
rx: radiiPx[X],
|
|
33371
|
+
ry: radiiPx[Y]
|
|
33372
|
+
}), /*#__PURE__*/React.createElement(DragHandle, {
|
|
33373
|
+
center: center
|
|
33374
|
+
}));
|
|
33375
|
+
}
|
|
33376
|
+
const dragHandleDimensions = [24, 14];
|
|
33377
|
+
const dragHandleDotPositions = crossProduct([-4.4, 0, 4.4], [-2.1, 2.1]);
|
|
33378
|
+
function DragHandle(props) {
|
|
33379
|
+
const {
|
|
33380
|
+
center
|
|
33381
|
+
} = props;
|
|
33382
|
+
const cornerRadius = Math.min(...dragHandleDimensions) / 2;
|
|
33383
|
+
const [centerPx] = useTransformVectorsToPixels(center);
|
|
33384
|
+
const topLeft = vec.sub(centerPx, vec.scale(dragHandleDimensions, 0.5));
|
|
33385
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("rect", {
|
|
33386
|
+
className: "movable-circle-handle",
|
|
33387
|
+
x: topLeft[X],
|
|
33388
|
+
y: topLeft[Y],
|
|
33389
|
+
width: dragHandleDimensions[X],
|
|
33390
|
+
height: dragHandleDimensions[Y],
|
|
33391
|
+
rx: cornerRadius,
|
|
33392
|
+
ry: cornerRadius
|
|
33393
|
+
}), dragHandleDotPositions.map(offsetPx => {
|
|
33394
|
+
const [xPx, yPx] = vec.add(offsetPx, centerPx);
|
|
33395
|
+
return /*#__PURE__*/React.createElement("circle", {
|
|
33396
|
+
key: `circle-${xPx}-${yPx}`,
|
|
33397
|
+
className: "movable-circle-handle-dot",
|
|
33398
|
+
cx: xPx,
|
|
33399
|
+
cy: yPx
|
|
33400
|
+
});
|
|
33401
|
+
}));
|
|
33402
|
+
}
|
|
33403
|
+
function crossProduct(as, bs) {
|
|
33404
|
+
const result = [];
|
|
33405
|
+
for (const a of as) {
|
|
33406
|
+
for (const b of bs) {
|
|
33407
|
+
result.push([a, b]);
|
|
33408
|
+
}
|
|
33409
|
+
}
|
|
33410
|
+
return result;
|
|
33411
|
+
}
|
|
32752
33412
|
|
|
33413
|
+
function renderLinearGraph(state, dispatch) {
|
|
33414
|
+
return {
|
|
33415
|
+
graph: /*#__PURE__*/React.createElement(LinearGraph, {
|
|
33416
|
+
graphState: state,
|
|
33417
|
+
dispatch: dispatch
|
|
33418
|
+
}),
|
|
33419
|
+
interactiveElementsDescription: null
|
|
33420
|
+
};
|
|
33421
|
+
}
|
|
32753
33422
|
const LinearGraph = (props, key) => {
|
|
32754
33423
|
const {
|
|
32755
33424
|
dispatch
|
|
@@ -32776,6 +33445,15 @@ const LinearGraph = (props, key) => {
|
|
|
32776
33445
|
});
|
|
32777
33446
|
};
|
|
32778
33447
|
|
|
33448
|
+
function renderLinearSystemGraph(state, dispatch) {
|
|
33449
|
+
return {
|
|
33450
|
+
graph: /*#__PURE__*/React.createElement(LinearSystemGraph, {
|
|
33451
|
+
graphState: state,
|
|
33452
|
+
dispatch: dispatch
|
|
33453
|
+
}),
|
|
33454
|
+
interactiveElementsDescription: null
|
|
33455
|
+
};
|
|
33456
|
+
}
|
|
32779
33457
|
const LinearSystemGraph = props => {
|
|
32780
33458
|
const {
|
|
32781
33459
|
dispatch
|
|
@@ -32798,405 +33476,122 @@ const LinearSystemGraph = props => {
|
|
|
32798
33476
|
})), ";");
|
|
32799
33477
|
};
|
|
32800
33478
|
|
|
32801
|
-
|
|
33479
|
+
function renderPointGraph(state, dispatch) {
|
|
33480
|
+
return {
|
|
33481
|
+
graph: /*#__PURE__*/React.createElement(PointGraph, {
|
|
33482
|
+
graphState: state,
|
|
33483
|
+
dispatch: dispatch
|
|
33484
|
+
}),
|
|
33485
|
+
interactiveElementsDescription: /*#__PURE__*/React.createElement(PointGraphDescription, {
|
|
33486
|
+
state: state
|
|
33487
|
+
})
|
|
33488
|
+
};
|
|
33489
|
+
}
|
|
33490
|
+
function PointGraph(props) {
|
|
33491
|
+
const numPoints = props.graphState.numPoints;
|
|
33492
|
+
if (numPoints === "unlimited") {
|
|
33493
|
+
return UnlimitedPointGraph(props);
|
|
33494
|
+
}
|
|
33495
|
+
return LimitedPointGraph(props);
|
|
33496
|
+
}
|
|
33497
|
+
function LimitedPointGraph(props) {
|
|
32802
33498
|
const {
|
|
32803
33499
|
dispatch
|
|
32804
33500
|
} = props;
|
|
33501
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, props.graphState.coords.map((point, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33502
|
+
key: i,
|
|
33503
|
+
point: point,
|
|
33504
|
+
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination))
|
|
33505
|
+
})));
|
|
33506
|
+
}
|
|
33507
|
+
function UnlimitedPointGraph(props) {
|
|
32805
33508
|
const {
|
|
32806
|
-
|
|
32807
|
-
} = props
|
|
32808
|
-
const
|
|
32809
|
-
const
|
|
32810
|
-
|
|
32811
|
-
|
|
32812
|
-
|
|
32813
|
-
|
|
32814
|
-
|
|
32815
|
-
|
|
32816
|
-
|
|
32817
|
-
|
|
32818
|
-
|
|
32819
|
-
|
|
32820
|
-
|
|
32821
|
-
|
|
32822
|
-
|
|
32823
|
-
/**
|
|
32824
|
-
* Wrapper with Mafs transform styles for SVG elements.
|
|
32825
|
-
* Scales and translates the SVG element to match the Mafs view.
|
|
32826
|
-
* Use if you do not need/want to use the hook in `use-transform.ts`.
|
|
32827
|
-
*/
|
|
32828
|
-
const MafsCssTransformWrapper = ({
|
|
32829
|
-
children
|
|
32830
|
-
}) => /*#__PURE__*/React.createElement("g", {
|
|
32831
|
-
style: {
|
|
32832
|
-
transform: `var(--mafs-view-transform) var(--mafs-user-transform)`
|
|
32833
|
-
}
|
|
32834
|
-
}, children);
|
|
32835
|
-
|
|
32836
|
-
const _excluded$1 = ["children"];
|
|
32837
|
-
const TextLabel = _ref => {
|
|
32838
|
-
let {
|
|
32839
|
-
children
|
|
32840
|
-
} = _ref,
|
|
32841
|
-
rest = _objectWithoutPropertiesLoose(_ref, _excluded$1);
|
|
32842
|
-
return /*#__PURE__*/React__default.createElement(Text$1, _extends({
|
|
32843
|
-
size: 16,
|
|
32844
|
-
svgTextProps: {
|
|
32845
|
-
filter: "url(#background)",
|
|
32846
|
-
fontWeight: "bold"
|
|
33509
|
+
dispatch
|
|
33510
|
+
} = props;
|
|
33511
|
+
const graphConfig = useGraphConfig();
|
|
33512
|
+
const {
|
|
33513
|
+
range: [[minX, maxX], [minY, maxY]]
|
|
33514
|
+
} = graphConfig;
|
|
33515
|
+
const width = maxX - minX;
|
|
33516
|
+
const height = maxY - minY;
|
|
33517
|
+
const [[widthPx, heightPx]] = useTransformDimensionsToPixels([width, height]);
|
|
33518
|
+
const [[left, top]] = useTransformVectorsToPixels([minX, maxY]);
|
|
33519
|
+
const itemsRef = React.useRef([]);
|
|
33520
|
+
React.useEffect(() => {
|
|
33521
|
+
const focusedIndex = props.graphState.focusedPointIndex;
|
|
33522
|
+
if (focusedIndex != null) {
|
|
33523
|
+
var _itemsRef$current$foc;
|
|
33524
|
+
(_itemsRef$current$foc = itemsRef.current[focusedIndex]) == null || _itemsRef$current$foc.focus();
|
|
32847
33525
|
}
|
|
32848
|
-
},
|
|
32849
|
-
|
|
32850
|
-
|
|
32851
|
-
|
|
32852
|
-
|
|
32853
|
-
|
|
32854
|
-
|
|
32855
|
-
|
|
32856
|
-
|
|
32857
|
-
|
|
32858
|
-
|
|
32859
|
-
|
|
32860
|
-
|
|
32861
|
-
|
|
32862
|
-
|
|
32863
|
-
|
|
32864
|
-
const PolygonAngle = ({
|
|
32865
|
-
centerPoint,
|
|
32866
|
-
endPoints,
|
|
32867
|
-
range,
|
|
32868
|
-
polygonLines,
|
|
32869
|
-
showAngles,
|
|
32870
|
-
snapTo
|
|
32871
|
-
}) => {
|
|
32872
|
-
const [centerX, centerY] = centerPoint;
|
|
32873
|
-
const areClockwise = clockwise$1([centerPoint, ...endPoints]);
|
|
32874
|
-
const [[startX, startY], [endX, endY]] = areClockwise ? endPoints : endPoints.reverse();
|
|
32875
|
-
const radius = 0.3;
|
|
32876
|
-
const a = vec.dist(centerPoint, endPoints[0]);
|
|
32877
|
-
const b = vec.dist(centerPoint, endPoints[1]);
|
|
32878
|
-
const c = vec.dist(endPoints[0], endPoints[1]);
|
|
32879
|
-
|
|
32880
|
-
// Law of cosines
|
|
32881
|
-
const angle = Math.acos((a ** 2 + b ** 2 - c ** 2) / (2 * a * b));
|
|
32882
|
-
const y1 = centerY + (startY - centerY) / a * radius;
|
|
32883
|
-
const x2 = centerX + (endX - centerX) / b * radius;
|
|
32884
|
-
const x1 = centerX + (startX - centerX) / a * radius;
|
|
32885
|
-
const y2 = centerY + (endY - centerY) / b * radius;
|
|
32886
|
-
|
|
32887
|
-
// Fourth point that would create a rhomboid
|
|
32888
|
-
// Used to calculate the inside of the angle and to create square
|
|
32889
|
-
const [x3, y3] = vec.add(centerPoint, vec.add(vec.sub([x1, y1], centerPoint), vec.sub([x2, y2], centerPoint)));
|
|
32890
|
-
if (!showAngles) {
|
|
32891
|
-
return isRightPolygonAngle(angle) ? /*#__PURE__*/React.createElement(RightAngleSquare, {
|
|
32892
|
-
start: [x1, y1],
|
|
32893
|
-
vertex: [x2, y2],
|
|
32894
|
-
end: [x3, y3]
|
|
32895
|
-
}) : null;
|
|
32896
|
-
}
|
|
32897
|
-
|
|
32898
|
-
// Midpoint betwen ends of arc
|
|
32899
|
-
const isOutside = shouldDrawArcOutside([x3, y3], centerPoint, range, polygonLines);
|
|
32900
|
-
const largeArcFlag = isOutside ? 1 : 0;
|
|
32901
|
-
const sweepFlag = isOutside ? 1 : 0;
|
|
32902
|
-
const arc = `M ${x1} ${y1} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${x2} ${y2}`;
|
|
32903
|
-
let angleInDegrees = angle * (180 / Math.PI);
|
|
32904
|
-
// If we have triggered "largArcFlag", the angle should be greater than 180
|
|
32905
|
-
if (isOutside) {
|
|
32906
|
-
angleInDegrees = 360 - angleInDegrees;
|
|
32907
|
-
}
|
|
32908
|
-
|
|
32909
|
-
// Only want to show whole numbers when in angles mode
|
|
32910
|
-
const angleLabelNumber = parseFloat(angleInDegrees.toFixed(snapTo === "angles" ? 0 : 1));
|
|
32911
|
-
const angleLabel = Number.isInteger(angleLabelNumber) ? angleLabelNumber : "≈ " + angleLabelNumber;
|
|
32912
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("filter", {
|
|
32913
|
-
id: "background",
|
|
32914
|
-
x: "-5%",
|
|
32915
|
-
width: "110%",
|
|
32916
|
-
y: "0%",
|
|
32917
|
-
height: "100%"
|
|
32918
|
-
}, /*#__PURE__*/React.createElement("feFlood", {
|
|
32919
|
-
floodColor: "#FFF",
|
|
32920
|
-
floodOpacity: "0.5"
|
|
32921
|
-
}), /*#__PURE__*/React.createElement("feComposite", {
|
|
32922
|
-
operator: "over",
|
|
32923
|
-
in: "SourceGraphic"
|
|
32924
|
-
}))), !isOutside && isRightAngle(angle) ? /*#__PURE__*/React.createElement(RightAngleSquare, {
|
|
32925
|
-
start: [x1, y1],
|
|
32926
|
-
vertex: [x2, y2],
|
|
32927
|
-
end: [x3, y3]
|
|
32928
|
-
}) : /*#__PURE__*/React.createElement(Arc, {
|
|
32929
|
-
arc: arc
|
|
32930
|
-
}), /*#__PURE__*/React.createElement(TextLabel, {
|
|
32931
|
-
x: x3,
|
|
32932
|
-
y: y3,
|
|
32933
|
-
attach: y3 - centerY > 0 ? "s" : "n",
|
|
32934
|
-
attachDistance: Math.abs(y3 - centerY) < 0.2 || vec.dist([x3, y3], centerPoint) < 0.3 ? 20 : 10
|
|
32935
|
-
}, angleLabel, "\xB0"));
|
|
32936
|
-
};
|
|
32937
|
-
const Angle = ({
|
|
32938
|
-
vertex,
|
|
32939
|
-
coords,
|
|
32940
|
-
showAngles,
|
|
32941
|
-
allowReflexAngles,
|
|
32942
|
-
range
|
|
32943
|
-
}) => {
|
|
32944
|
-
// Check if the points are clockwise or not, depending on whether we allow reflex angles
|
|
32945
|
-
const areClockwise = clockwise$1([...coords, vertex]);
|
|
32946
|
-
const shouldReverseCoords = areClockwise && !allowReflexAngles;
|
|
32947
|
-
|
|
32948
|
-
// Reverse the coordinates accordingly to ensure the angle is calculated correctly
|
|
32949
|
-
const clockwiseCoords = shouldReverseCoords ? coords : coords.reverse();
|
|
32950
|
-
|
|
32951
|
-
// Calculate the angles between the two points
|
|
32952
|
-
const startAngle = getAngleFromVertex(clockwiseCoords[0], vertex);
|
|
32953
|
-
const endAngle = getAngleFromVertex(clockwiseCoords[1], vertex);
|
|
32954
|
-
const angle = (startAngle + 360 - endAngle) % 360;
|
|
32955
|
-
|
|
32956
|
-
// Check if the angle is reflexive
|
|
32957
|
-
const isReflexive = angle > 180;
|
|
32958
|
-
|
|
32959
|
-
// Break out the necessary points for the arc calculation
|
|
32960
|
-
const [centerX, centerY] = vertex;
|
|
32961
|
-
const [point1, point2] = clockwiseCoords;
|
|
32962
|
-
const [startX, startY] = point1;
|
|
32963
|
-
const [endX, endY] = point2;
|
|
32964
|
-
const a = vec.dist(vertex, point1);
|
|
32965
|
-
const b = vec.dist(vertex, point2);
|
|
32966
|
-
|
|
32967
|
-
// Set the radius of the arc
|
|
32968
|
-
const radius = 2;
|
|
32969
|
-
|
|
32970
|
-
// Calculate the end points of the arc
|
|
32971
|
-
const y1 = centerY + (startY - centerY) / a * radius;
|
|
32972
|
-
const x2 = centerX + (endX - centerX) / b * radius;
|
|
32973
|
-
const x1 = centerX + (startX - centerX) / a * radius;
|
|
32974
|
-
const y2 = centerY + (endY - centerY) / b * radius;
|
|
32975
|
-
|
|
32976
|
-
// Used to calculate the inside of the angle and to create square
|
|
32977
|
-
const [x3, y3] = vec.add(vertex, vec.add(vec.sub([x1, y1], vertex), vec.sub([x2, y2], vertex)));
|
|
32978
|
-
|
|
32979
|
-
// Determine whether the arc should be drawn outside the angle
|
|
32980
|
-
const isOutside = shouldDrawArcOutside([x3, y3], vertex, range, [[vertex, point1], [vertex, point2]]);
|
|
32981
|
-
|
|
32982
|
-
// Determine the flags for the arc
|
|
32983
|
-
// If the angle is outside OR reflexive, we want to draw a large arc
|
|
32984
|
-
// If the angle is outside AND reflexive, we want to sweep the arc
|
|
32985
|
-
const largeArcFlag = isOutside || isReflexive ? 1 : 0;
|
|
32986
|
-
const sweepFlag = isOutside && isReflexive ? 1 : 0;
|
|
32987
|
-
|
|
32988
|
-
// Create the SVG path for the arc
|
|
32989
|
-
const arc = `M ${x1} ${y1} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${x2} ${y2}`;
|
|
32990
|
-
|
|
32991
|
-
// We only ever want to show whole angles
|
|
32992
|
-
const angleLabel = parseFloat(angle.toFixed(0)); // Only want to show whole angles
|
|
32993
|
-
|
|
32994
|
-
// Calculate the text position based on the angle and whether we allow reflex angles
|
|
32995
|
-
// Let's try the angle bisector method to find the midpoint of the arc
|
|
32996
|
-
const [textX, textY] = calculateBisectorPoint(point1, point2, vertex, isReflexive, allowReflexAngles, radius);
|
|
32997
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("filter", {
|
|
32998
|
-
id: "background",
|
|
32999
|
-
x: "-5%",
|
|
33000
|
-
width: "110%",
|
|
33001
|
-
y: "0%",
|
|
33002
|
-
height: "100%"
|
|
33003
|
-
}, /*#__PURE__*/React.createElement("feFlood", {
|
|
33004
|
-
floodColor: "#FFF",
|
|
33005
|
-
floodOpacity: "0.5"
|
|
33006
|
-
}), /*#__PURE__*/React.createElement("feComposite", {
|
|
33007
|
-
operator: "over",
|
|
33008
|
-
in: "SourceGraphic"
|
|
33009
|
-
}))), isRightAngle(angle) ? /*#__PURE__*/React.createElement(RightAngleSquare, {
|
|
33010
|
-
start: [x1, y1],
|
|
33011
|
-
vertex: [x2, y2],
|
|
33012
|
-
end: [x3, y3],
|
|
33013
|
-
className: "arc-right-angle"
|
|
33014
|
-
}) : /*#__PURE__*/React.createElement(Arc, {
|
|
33015
|
-
arc: arc,
|
|
33016
|
-
className: "angle-arc"
|
|
33017
|
-
}), showAngles && /*#__PURE__*/React.createElement(TextLabel, {
|
|
33018
|
-
x: textX,
|
|
33019
|
-
y: textY,
|
|
33020
|
-
color: color.blue
|
|
33021
|
-
}, angleLabel, "\xB0"));
|
|
33022
|
-
};
|
|
33023
|
-
|
|
33024
|
-
/**
|
|
33025
|
-
* This is broken out into its own component so that it can be used for an early return
|
|
33026
|
-
* (see line 55 or https://github.com/Khan/perseus/blob/84bbd882b11d16871e1b813a0b901f3b903d5479/packages/perseus/src/widgets/interactive-graphs/graphs/components/angle.tsx#L53-L57)
|
|
33027
|
-
*/
|
|
33028
|
-
const RightAngleSquare = ({
|
|
33029
|
-
start: [x1, y1],
|
|
33030
|
-
vertex: [x2, y2],
|
|
33031
|
-
end: [x3, y3],
|
|
33032
|
-
className
|
|
33033
|
-
}) => /*#__PURE__*/React.createElement(MafsCssTransformWrapper, null, /*#__PURE__*/React.createElement("path", {
|
|
33034
|
-
d: `M ${x1} ${y1} L ${x3} ${y3} M ${x3} ${y3} L ${x2} ${y2}`,
|
|
33035
|
-
strokeWidth: 0.02,
|
|
33036
|
-
fill: "none",
|
|
33037
|
-
className: className
|
|
33038
|
-
}));
|
|
33039
|
-
|
|
33040
|
-
// We're conditionally adding the class name here so that we can style the arc differently
|
|
33041
|
-
// based on whether it's an angle or a polygon angle
|
|
33042
|
-
const Arc = ({
|
|
33043
|
-
arc,
|
|
33044
|
-
className
|
|
33045
|
-
}) => {
|
|
33046
|
-
return /*#__PURE__*/React.createElement(MafsCssTransformWrapper, null, /*#__PURE__*/React.createElement("path", {
|
|
33047
|
-
d: arc,
|
|
33048
|
-
strokeWidth: 0.02,
|
|
33049
|
-
fill: "none",
|
|
33050
|
-
className: className
|
|
33051
|
-
}));
|
|
33052
|
-
};
|
|
33053
|
-
const isRightPolygonAngle = angle => Math.abs(angle - Math.PI / 2) < 0.01;
|
|
33054
|
-
const isRightAngle = angle => Math.round(angle) === 90;
|
|
33055
|
-
|
|
33056
|
-
/**
|
|
33057
|
-
* Determines if an angle is an inside (false) or outside (true) angle.
|
|
33058
|
-
* They way, we know to flip the `largeArc` and `sweepArc` flags.
|
|
33059
|
-
* Uses the priciple that a ray from a point inside a polygon will intersect
|
|
33060
|
-
* with an odd number of lines, while a ray from a point outside the polygon
|
|
33061
|
-
* will intersect with an even number of lines.
|
|
33062
|
-
* https://stackoverflow.com/questions/217578/how-can-i-determine-whether-a-2d-point-is-within-a-polygon
|
|
33063
|
-
*/
|
|
33064
|
-
const shouldDrawArcOutside = (midpoint, vertex, range, polygonLines) => {
|
|
33065
|
-
// Create a ray from the midpoint (inside angle) to the edge of the range
|
|
33066
|
-
const rangeIntersectionPoint = getIntersectionOfRayWithBox(midpoint, vertex, range);
|
|
33067
|
-
let lineIntersectionCount = 0;
|
|
33068
|
-
polygonLines.forEach(line => segmentsIntersect([vertex, rangeIntersectionPoint], line) && lineIntersectionCount++);
|
|
33069
|
-
|
|
33070
|
-
// If the number of intersections is even, the angle is inside the polygon
|
|
33071
|
-
return !isEven(lineIntersectionCount);
|
|
33072
|
-
};
|
|
33073
|
-
const isEven = n => n % 2 === 0;
|
|
33074
|
-
|
|
33075
|
-
// This function calculates the bisector point of an angle formed by two points
|
|
33076
|
-
// and a vertex. It is used to position the angle label so that it is always
|
|
33077
|
-
// outside the arc at the exact midpoint of the angle.
|
|
33078
|
-
// Reflex angles make use of polar coordinates to determine the correct direction
|
|
33079
|
-
function calculateBisectorPoint(point1, point2, vertex, isReflex, allowReflex, arcRadius) {
|
|
33080
|
-
const [originX, originY] = vertex;
|
|
33081
|
-
const [x1, y1] = point1;
|
|
33082
|
-
const [x2, y2] = point2;
|
|
33083
|
-
|
|
33084
|
-
// Convert the Cartesian Coordinates to vectors
|
|
33085
|
-
const vectorA = [x1 - originX, y1 - originY];
|
|
33086
|
-
const vectorB = [x2 - originX, y2 - originY];
|
|
33087
|
-
|
|
33088
|
-
// Calculate the average angle of the vectors
|
|
33089
|
-
// so that we can point the bisector in the correct direction using polar coordinates
|
|
33090
|
-
const angleA = Math.atan2(vectorA[1], vectorA[0]);
|
|
33091
|
-
const angleB = Math.atan2(vectorB[1], vectorB[0]);
|
|
33092
|
-
|
|
33093
|
-
// Calculate the average of these two angles
|
|
33094
|
-
let averageAngle = (angleA + angleB) / 2;
|
|
33095
|
-
const angleRadians = Math.abs(angleA - angleB);
|
|
33096
|
-
|
|
33097
|
-
// Adjust the average angle to point in the correct direction
|
|
33098
|
-
// and to account for reflex angles and a bug with 180 degrees
|
|
33099
|
-
// that occurs due to our angleOffsetDegrees option in the graph
|
|
33100
|
-
if (allowReflex) {
|
|
33101
|
-
// If the resulting angles are less than 180 degrees,
|
|
33102
|
-
// or if the user has flipped the points on the interactive element
|
|
33103
|
-
// ensure that we have the correct direction for the reflex angle
|
|
33104
|
-
if (angleRadians <= Math.PI && isReflex || angleB > angleA) {
|
|
33105
|
-
averageAngle += Math.PI; // Add 180 degrees
|
|
33106
|
-
}
|
|
33107
|
-
} else {
|
|
33108
|
-
// If the resulting angles are greater than 180 degrees, adjust
|
|
33109
|
-
// to get the correct angle, as we already know that the angle is not reflexive
|
|
33110
|
-
// This fixes a bug that occurs at 180 degrees due to our angleOffsetDegrees option in the graph
|
|
33111
|
-
if (angleRadians > Math.PI) {
|
|
33112
|
-
averageAngle -= Math.PI; // Subract 180 degrees
|
|
33526
|
+
}, [props.graphState.focusedPointIndex, itemsRef]);
|
|
33527
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("rect", {
|
|
33528
|
+
style: {
|
|
33529
|
+
fill: "rgba(0,0,0,0)",
|
|
33530
|
+
cursor: "crosshair"
|
|
33531
|
+
},
|
|
33532
|
+
width: widthPx,
|
|
33533
|
+
height: heightPx,
|
|
33534
|
+
x: left,
|
|
33535
|
+
y: top,
|
|
33536
|
+
onClick: event => {
|
|
33537
|
+
const elementRect = event.currentTarget.getBoundingClientRect();
|
|
33538
|
+
const x = event.clientX - elementRect.x;
|
|
33539
|
+
const y = event.clientY - elementRect.y;
|
|
33540
|
+
const graphCoordinates = pixelsToVectors([[x, y]], graphConfig);
|
|
33541
|
+
dispatch(actions.pointGraph.addPoint(graphCoordinates[0]));
|
|
33113
33542
|
}
|
|
33114
|
-
}
|
|
33115
|
-
|
|
33116
|
-
|
|
33117
|
-
|
|
33118
|
-
|
|
33119
|
-
// Calculate the magnitude of the sum to normalize it
|
|
33120
|
-
const sumMagnitude = Math.sqrt(sum[0] ** 2 + sum[1] ** 2);
|
|
33121
|
-
const bisectorDirection = [sum[0] / sumMagnitude, sum[1] / sumMagnitude];
|
|
33122
|
-
|
|
33123
|
-
// Calculate the initial distance of the bisector direction from the origin
|
|
33124
|
-
const initialDistance = Math.sqrt(bisectorDirection[0] ** 2 + bisectorDirection[1] ** 2);
|
|
33125
|
-
|
|
33126
|
-
// Determine the minimum radius to ensure that the text is always outside the arc
|
|
33127
|
-
const requiredDistance = arcRadius * 1.75;
|
|
33128
|
-
let radius = requiredDistance / initialDistance;
|
|
33129
|
-
|
|
33130
|
-
// Apply radius only if the initial distance is less than required
|
|
33131
|
-
if (initialDistance >= requiredDistance) {
|
|
33132
|
-
radius = 1; // Use the unit vector as is
|
|
33133
|
-
}
|
|
33134
|
-
|
|
33135
|
-
// Scale the bisector direction by the radius
|
|
33136
|
-
const bisectorPoint = [bisectorDirection[0] * radius, bisectorDirection[1] * radius];
|
|
33137
|
-
|
|
33138
|
-
// Add the vertex to the bisector point to get the final position
|
|
33139
|
-
// to ensure that the angle label moves with the interactive element
|
|
33140
|
-
const scaledBisector = vec.add(bisectorPoint, vertex);
|
|
33141
|
-
return scaledBisector;
|
|
33142
|
-
}
|
|
33143
|
-
|
|
33144
|
-
const MovablePoint$1 = /*#__PURE__*/React.forwardRef((props, pointRef) => {
|
|
33145
|
-
const {
|
|
33146
|
-
snapStep
|
|
33147
|
-
} = useGraphConfig();
|
|
33148
|
-
const elementRef = useRef(null);
|
|
33149
|
-
const {
|
|
33150
|
-
point,
|
|
33151
|
-
onMove = () => {},
|
|
33152
|
-
onFocusChange = () => {},
|
|
33153
|
-
onClick = () => {},
|
|
33154
|
-
cursor,
|
|
33155
|
-
color: color$1 = color.blue,
|
|
33156
|
-
constrain = p => snap(snapStep, p)
|
|
33157
|
-
} = props;
|
|
33158
|
-
const {
|
|
33159
|
-
dragging
|
|
33160
|
-
} = useDraggable({
|
|
33161
|
-
gestureTarget: elementRef,
|
|
33162
|
-
point,
|
|
33163
|
-
onMove,
|
|
33164
|
-
constrainKeyboardMovement: constrain
|
|
33165
|
-
});
|
|
33166
|
-
return /*#__PURE__*/React.createElement(MovablePointView, {
|
|
33543
|
+
}), props.graphState.coords.map((point, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33544
|
+
key: i,
|
|
33545
|
+
point: point,
|
|
33546
|
+
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination)),
|
|
33167
33547
|
ref: ref => {
|
|
33168
|
-
|
|
33169
|
-
// function or a MutableRefObject. Mostly this is to satisfy
|
|
33170
|
-
// the type system, the function branch seems to be the only
|
|
33171
|
-
// one that occurs
|
|
33172
|
-
if (typeof pointRef === "function") {
|
|
33173
|
-
pointRef(ref);
|
|
33174
|
-
} else if (pointRef !== null) {
|
|
33175
|
-
pointRef.current = ref;
|
|
33176
|
-
}
|
|
33177
|
-
|
|
33178
|
-
// This ref is for the useDraggable and is not passed up the
|
|
33179
|
-
// chain
|
|
33180
|
-
elementRef.current = ref;
|
|
33548
|
+
itemsRef.current[i] = ref;
|
|
33181
33549
|
},
|
|
33182
|
-
|
|
33183
|
-
|
|
33184
|
-
dragging: dragging,
|
|
33185
|
-
focusBehavior: {
|
|
33186
|
-
type: "uncontrolled",
|
|
33187
|
-
tabIndex: 0,
|
|
33188
|
-
onFocusChange
|
|
33550
|
+
onFocus: () => {
|
|
33551
|
+
dispatch(actions.pointGraph.focusPoint(i));
|
|
33189
33552
|
},
|
|
33190
33553
|
onClick: () => {
|
|
33191
|
-
|
|
33192
|
-
|
|
33193
|
-
|
|
33194
|
-
|
|
33195
|
-
|
|
33554
|
+
dispatch(actions.pointGraph.clickPoint(i));
|
|
33555
|
+
}
|
|
33556
|
+
})));
|
|
33557
|
+
}
|
|
33558
|
+
function PointGraphDescription({
|
|
33559
|
+
state
|
|
33560
|
+
}) {
|
|
33561
|
+
// PointGraphDescription needs to `usePerseusI18n`, so it has to be a
|
|
33562
|
+
// component rather than a function that simply returns a string.
|
|
33563
|
+
const i18n = usePerseusI18n();
|
|
33564
|
+
return describePointGraph(state, i18n);
|
|
33565
|
+
}
|
|
33566
|
+
|
|
33567
|
+
// Exported for testing
|
|
33568
|
+
function describePointGraph(state, i18n) {
|
|
33569
|
+
const {
|
|
33570
|
+
strings,
|
|
33571
|
+
locale
|
|
33572
|
+
} = i18n;
|
|
33573
|
+
if (state.coords.length === 0) {
|
|
33574
|
+
return strings.srNoInteractiveElements;
|
|
33575
|
+
}
|
|
33576
|
+
const pointDescriptions = state.coords.map(([x, y]) => strings.srPointAtCoordinates({
|
|
33577
|
+
x: srFormatNumber(x, locale),
|
|
33578
|
+
y: srFormatNumber(y, locale)
|
|
33579
|
+
}));
|
|
33580
|
+
return strings.srInteractiveElements({
|
|
33581
|
+
elements: pointDescriptions.join(", ")
|
|
33196
33582
|
});
|
|
33197
|
-
}
|
|
33583
|
+
}
|
|
33198
33584
|
|
|
33199
|
-
|
|
33585
|
+
function renderPolygonGraph(state, dispatch) {
|
|
33586
|
+
return {
|
|
33587
|
+
graph: /*#__PURE__*/React.createElement(PolygonGraph, {
|
|
33588
|
+
graphState: state,
|
|
33589
|
+
dispatch: dispatch
|
|
33590
|
+
}),
|
|
33591
|
+
interactiveElementsDescription: null
|
|
33592
|
+
};
|
|
33593
|
+
}
|
|
33594
|
+
const LimitedPolygonGraph = props => {
|
|
33200
33595
|
const [hovered, setHovered] = React.useState(false);
|
|
33201
33596
|
// This is more so required for the re-rendering that occurs when state
|
|
33202
33597
|
// updates; specifically with regard to line weighting and polygon focus.
|
|
@@ -33307,6 +33702,153 @@ const PolygonGraph = props => {
|
|
|
33307
33702
|
}
|
|
33308
33703
|
})));
|
|
33309
33704
|
};
|
|
33705
|
+
|
|
33706
|
+
// TODO(catjohnson): reduce redundancy between LimitedPolygonGraph and UnlimitedPolygonGraph
|
|
33707
|
+
// both components are vary similar, however more implementation is needed to be added before
|
|
33708
|
+
// it is clear what can and can't be shared between components.
|
|
33709
|
+
const UnlimitedPolygonGraph = props => {
|
|
33710
|
+
const [hovered, setHovered] = React.useState(false);
|
|
33711
|
+
// This is more so required for the re-rendering that occurs when state
|
|
33712
|
+
// updates; specifically with regard to line weighting and polygon focus.
|
|
33713
|
+
const [focusVisible, setFocusVisible] = React.useState(false);
|
|
33714
|
+
const {
|
|
33715
|
+
dispatch
|
|
33716
|
+
} = props;
|
|
33717
|
+
const {
|
|
33718
|
+
coords,
|
|
33719
|
+
showAngles,
|
|
33720
|
+
showSides,
|
|
33721
|
+
range,
|
|
33722
|
+
snapStep,
|
|
33723
|
+
snapTo = "grid"
|
|
33724
|
+
} = props.graphState;
|
|
33725
|
+
const graphConfig = useGraphConfig();
|
|
33726
|
+
|
|
33727
|
+
// TODO(catjohnson): Explore abstracting this code as it is similar to point.tsx
|
|
33728
|
+
// and hopefully we can cut down ont the unlimited graph redundancy.
|
|
33729
|
+
const {
|
|
33730
|
+
range: [x, y],
|
|
33731
|
+
disableKeyboardInteraction,
|
|
33732
|
+
graphDimensionsInPixels
|
|
33733
|
+
} = graphConfig;
|
|
33734
|
+
const widthPx = graphDimensionsInPixels[0];
|
|
33735
|
+
const heightPx = graphDimensionsInPixels[1];
|
|
33736
|
+
const [[left, top]] = useTransformVectorsToPixels([x[0], y[1]]);
|
|
33737
|
+
const pointRef = React.useRef([]);
|
|
33738
|
+
|
|
33739
|
+
// TODO(benchristel): can the default set of points be removed here? I don't
|
|
33740
|
+
// think coords can be null.
|
|
33741
|
+
const points = coords != null ? coords : [[0, 0]];
|
|
33742
|
+
const polygonRef = React.useRef(null);
|
|
33743
|
+
const dragReferencePoint = points[0];
|
|
33744
|
+
const constrain = ["angles", "sides"].includes(snapTo) ? p => p : p => snap(snapStep, p);
|
|
33745
|
+
const {
|
|
33746
|
+
dragging
|
|
33747
|
+
} = useDraggable({
|
|
33748
|
+
gestureTarget: polygonRef,
|
|
33749
|
+
point: dragReferencePoint,
|
|
33750
|
+
onMove: newPoint => {
|
|
33751
|
+
const delta = vec.sub(newPoint, dragReferencePoint);
|
|
33752
|
+
dispatch(actions.polygon.moveAll(delta));
|
|
33753
|
+
},
|
|
33754
|
+
constrainKeyboardMovement: constrain
|
|
33755
|
+
});
|
|
33756
|
+
const lines = getLines(points);
|
|
33757
|
+
React.useEffect(() => {
|
|
33758
|
+
const focusedIndex = props.graphState.focusedPointIndex;
|
|
33759
|
+
if (focusedIndex != null) {
|
|
33760
|
+
var _pointRef$current$foc;
|
|
33761
|
+
(_pointRef$current$foc = pointRef.current[focusedIndex]) == null || _pointRef$current$foc.focus();
|
|
33762
|
+
}
|
|
33763
|
+
}, [props.graphState.focusedPointIndex, pointRef]);
|
|
33764
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("rect", {
|
|
33765
|
+
style: {
|
|
33766
|
+
fill: "rgba(0,0,0,0)",
|
|
33767
|
+
cursor: "crosshair"
|
|
33768
|
+
},
|
|
33769
|
+
width: widthPx,
|
|
33770
|
+
height: heightPx,
|
|
33771
|
+
x: left,
|
|
33772
|
+
y: top,
|
|
33773
|
+
onClick: event => {
|
|
33774
|
+
const elementRect = event.currentTarget.getBoundingClientRect();
|
|
33775
|
+
const x = event.clientX - elementRect.x;
|
|
33776
|
+
const y = event.clientY - elementRect.y;
|
|
33777
|
+
const graphCoordinates = pixelsToVectors([[x, y]], graphConfig);
|
|
33778
|
+
dispatch(actions.polygon.addPoint(graphCoordinates[0]));
|
|
33779
|
+
}
|
|
33780
|
+
}), /*#__PURE__*/React.createElement(Polygon, {
|
|
33781
|
+
points: [...points],
|
|
33782
|
+
color: "var(--movable-line-stroke-color)",
|
|
33783
|
+
svgPolygonProps: {
|
|
33784
|
+
strokeWidth: focusVisible ? "var(--movable-line-stroke-weight-active)" : "var(--movable-line-stroke-weight)",
|
|
33785
|
+
style: {
|
|
33786
|
+
fill: "transparent"
|
|
33787
|
+
}
|
|
33788
|
+
}
|
|
33789
|
+
}), props.graphState.coords.map((point, i) => {
|
|
33790
|
+
const pt1 = points.at(i - 1);
|
|
33791
|
+
const pt2 = points[(i + 1) % points.length];
|
|
33792
|
+
if (!pt1 || !pt2) {
|
|
33793
|
+
return null;
|
|
33794
|
+
}
|
|
33795
|
+
return /*#__PURE__*/React.createElement(PolygonAngle, {
|
|
33796
|
+
key: "angle-" + i,
|
|
33797
|
+
centerPoint: point,
|
|
33798
|
+
endPoints: [pt1, pt2],
|
|
33799
|
+
range: range,
|
|
33800
|
+
polygonLines: lines,
|
|
33801
|
+
showAngles: !!showAngles,
|
|
33802
|
+
snapTo: snapTo
|
|
33803
|
+
});
|
|
33804
|
+
}), showSides && lines.map(([start, end], i) => {
|
|
33805
|
+
const [x, y] = vec.midpoint(start, end);
|
|
33806
|
+
const length = parseFloat(vec.dist(start, end).toFixed(snapTo === "sides" ? 0 : 1));
|
|
33807
|
+
return /*#__PURE__*/React.createElement(TextLabel, {
|
|
33808
|
+
key: "side-" + i,
|
|
33809
|
+
x: x,
|
|
33810
|
+
y: y
|
|
33811
|
+
}, !Number.isInteger(length) && "≈ ", length);
|
|
33812
|
+
}), /*#__PURE__*/React.createElement(Polygon, {
|
|
33813
|
+
points: [...points],
|
|
33814
|
+
color: "transparent",
|
|
33815
|
+
svgPolygonProps: {
|
|
33816
|
+
ref: polygonRef,
|
|
33817
|
+
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
33818
|
+
strokeWidth: TARGET_SIZE,
|
|
33819
|
+
style: {
|
|
33820
|
+
cursor: dragging ? "grabbing" : "grab",
|
|
33821
|
+
fill: hovered ? "var(--mafs-blue)" : "transparent"
|
|
33822
|
+
},
|
|
33823
|
+
onMouseEnter: () => setHovered(true),
|
|
33824
|
+
onMouseLeave: () => setHovered(false),
|
|
33825
|
+
// Required to remove line weighting when user clicks away
|
|
33826
|
+
// from the focused polygon
|
|
33827
|
+
onKeyDownCapture: () => {
|
|
33828
|
+
setFocusVisible(hasFocusVisible(polygonRef.current));
|
|
33829
|
+
},
|
|
33830
|
+
// Required for lines to darken on focus
|
|
33831
|
+
onFocus: () => setFocusVisible(hasFocusVisible(polygonRef.current)),
|
|
33832
|
+
// Required for line weighting to update on blur. Without this,
|
|
33833
|
+
// the user has to hover over the shape for it to update
|
|
33834
|
+
onBlur: () => setFocusVisible(hasFocusVisible(polygonRef.current)),
|
|
33835
|
+
className: "movable-polygon"
|
|
33836
|
+
}
|
|
33837
|
+
}), props.graphState.coords.map((point, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33838
|
+
key: i,
|
|
33839
|
+
point: point,
|
|
33840
|
+
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination)),
|
|
33841
|
+
ref: ref => {
|
|
33842
|
+
pointRef.current[i] = ref;
|
|
33843
|
+
},
|
|
33844
|
+
onFocus: () => {
|
|
33845
|
+
dispatch(actions.pointGraph.focusPoint(i));
|
|
33846
|
+
},
|
|
33847
|
+
onClick: () => {
|
|
33848
|
+
dispatch(actions.pointGraph.clickPoint(i));
|
|
33849
|
+
}
|
|
33850
|
+
})));
|
|
33851
|
+
};
|
|
33310
33852
|
function getLines(points) {
|
|
33311
33853
|
return points.map((point, i) => {
|
|
33312
33854
|
const next = points[(i + 1) % points.length];
|
|
@@ -33327,190 +33869,20 @@ const hasFocusVisible = element => {
|
|
|
33327
33869
|
return matches(":focus");
|
|
33328
33870
|
}
|
|
33329
33871
|
};
|
|
33872
|
+
const PolygonGraph = props => {
|
|
33873
|
+
const numSides = props.graphState.numSides;
|
|
33874
|
+
return numSides === "unlimited" ? UnlimitedPolygonGraph(props) : LimitedPolygonGraph(props);
|
|
33875
|
+
};
|
|
33330
33876
|
|
|
33331
|
-
function
|
|
33332
|
-
|
|
33333
|
-
|
|
33334
|
-
|
|
33335
|
-
|
|
33336
|
-
|
|
33337
|
-
|
|
33338
|
-
|
|
33339
|
-
}
|
|
33340
|
-
if (state.type === "segment" && initialGraph.type === "segment") {
|
|
33341
|
-
return _extends({}, initialGraph, {
|
|
33342
|
-
coords: state.coords
|
|
33343
|
-
});
|
|
33344
|
-
}
|
|
33345
|
-
if (state.type === "linear" && initialGraph.type === "linear") {
|
|
33346
|
-
return _extends({}, initialGraph, {
|
|
33347
|
-
coords: state.coords
|
|
33348
|
-
});
|
|
33349
|
-
}
|
|
33350
|
-
if (state.type === "ray" && initialGraph.type === "ray") {
|
|
33351
|
-
return _extends({}, initialGraph, {
|
|
33352
|
-
coords: state.coords
|
|
33353
|
-
});
|
|
33354
|
-
}
|
|
33355
|
-
if (state.type === "polygon" && initialGraph.type === "polygon") {
|
|
33356
|
-
return _extends({}, initialGraph, {
|
|
33357
|
-
coords: state.coords
|
|
33358
|
-
});
|
|
33359
|
-
}
|
|
33360
|
-
if (state.type === "point" && initialGraph.type === "point") {
|
|
33361
|
-
return _extends({}, initialGraph, {
|
|
33362
|
-
coords: state.coords
|
|
33363
|
-
});
|
|
33364
|
-
}
|
|
33365
|
-
if (state.type === "circle" && initialGraph.type === "circle") {
|
|
33366
|
-
return _extends({}, initialGraph, {
|
|
33367
|
-
center: state.center,
|
|
33368
|
-
radius: getRadius(state)
|
|
33369
|
-
});
|
|
33370
|
-
}
|
|
33371
|
-
if (state.type === "quadratic" && initialGraph.type === "quadratic") {
|
|
33372
|
-
return _extends({}, initialGraph, {
|
|
33373
|
-
coords: state.coords
|
|
33374
|
-
});
|
|
33375
|
-
}
|
|
33376
|
-
if (state.type === "sinusoid" && initialGraph.type === "sinusoid") {
|
|
33377
|
-
return _extends({}, initialGraph, {
|
|
33378
|
-
coords: state.coords
|
|
33379
|
-
});
|
|
33380
|
-
}
|
|
33381
|
-
if (state.type === "angle" && initialGraph.type === "angle") {
|
|
33382
|
-
// We're going to reverse the coords for scoring if the angle is clockwise and
|
|
33383
|
-
// we don't allow reflex angles. This is because the angle is largely defined
|
|
33384
|
-
// by the order of the points in the coords array, and we want to maintain
|
|
33385
|
-
// the same angle scoring with the legacy graph (which had a bug).
|
|
33386
|
-
// (LEMS-2190): When we remove the legacy graph, move this logic to the scoring function.
|
|
33387
|
-
const areClockwise = clockwise$1([state.coords[0], state.coords[2], state.coords[1]]);
|
|
33388
|
-
const shouldReverseCoords = areClockwise && !state.allowReflexAngles;
|
|
33389
|
-
const coords = shouldReverseCoords ? state.coords.slice().reverse() : state.coords;
|
|
33390
|
-
return _extends({}, initialGraph, {
|
|
33391
|
-
coords,
|
|
33392
|
-
allowReflexAngles: state.allowReflexAngles
|
|
33393
|
-
});
|
|
33394
|
-
}
|
|
33395
|
-
if (state.type === "none" && initialGraph.type === "none") {
|
|
33396
|
-
return {
|
|
33397
|
-
type: "none"
|
|
33398
|
-
};
|
|
33399
|
-
}
|
|
33400
|
-
throw new Error("Mafs is not yet implemented for graph type: " + initialGraph.type);
|
|
33401
|
-
}
|
|
33402
|
-
|
|
33403
|
-
/**
|
|
33404
|
-
* determine radius of a circle graph
|
|
33405
|
-
*
|
|
33406
|
-
* @param graph - the graph object containing the circle
|
|
33407
|
-
* @returns the radius of the circle
|
|
33408
|
-
*/
|
|
33409
|
-
function getRadius(graph) {
|
|
33410
|
-
const [centerX, centerY] = graph.center;
|
|
33411
|
-
const [edgeX, edgeY] = graph.radiusPoint;
|
|
33412
|
-
return Math.sqrt(Math.pow(edgeX - centerX, 2) + Math.pow(edgeY - centerY, 2));
|
|
33413
|
-
}
|
|
33414
|
-
|
|
33415
|
-
function CircleGraph(props) {
|
|
33416
|
-
const {
|
|
33417
|
-
dispatch,
|
|
33418
|
-
graphState
|
|
33419
|
-
} = props;
|
|
33420
|
-
const {
|
|
33421
|
-
center,
|
|
33422
|
-
radiusPoint
|
|
33423
|
-
} = graphState;
|
|
33424
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(MovableCircle, {
|
|
33425
|
-
center: center,
|
|
33426
|
-
radius: getRadius(graphState),
|
|
33427
|
-
onMove: c => dispatch(actions.circle.moveCenter(c))
|
|
33428
|
-
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33429
|
-
point: radiusPoint,
|
|
33430
|
-
cursor: "ew-resize",
|
|
33431
|
-
onMove: newRadiusPoint => {
|
|
33432
|
-
dispatch(actions.circle.moveRadiusPoint(newRadiusPoint));
|
|
33433
|
-
}
|
|
33434
|
-
}));
|
|
33435
|
-
}
|
|
33436
|
-
function MovableCircle(props) {
|
|
33437
|
-
const {
|
|
33438
|
-
center,
|
|
33439
|
-
radius,
|
|
33440
|
-
onMove
|
|
33441
|
-
} = props;
|
|
33442
|
-
const {
|
|
33443
|
-
snapStep,
|
|
33444
|
-
disableKeyboardInteraction
|
|
33445
|
-
} = useGraphConfig();
|
|
33446
|
-
const draggableRef = useRef(null);
|
|
33447
|
-
const {
|
|
33448
|
-
dragging
|
|
33449
|
-
} = useDraggable({
|
|
33450
|
-
gestureTarget: draggableRef,
|
|
33451
|
-
point: center,
|
|
33452
|
-
onMove,
|
|
33453
|
-
constrainKeyboardMovement: p => snap(snapStep, p)
|
|
33454
|
-
});
|
|
33455
|
-
const [centerPx] = useTransformVectorsToPixels(center);
|
|
33456
|
-
const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
|
|
33457
|
-
return /*#__PURE__*/React.createElement("g", {
|
|
33458
|
-
ref: draggableRef,
|
|
33459
|
-
tabIndex: disableKeyboardInteraction ? -1 : 0,
|
|
33460
|
-
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
|
|
33461
|
-
}, /*#__PURE__*/React.createElement("ellipse", {
|
|
33462
|
-
className: "focus-ring",
|
|
33463
|
-
cx: centerPx[X],
|
|
33464
|
-
cy: centerPx[Y],
|
|
33465
|
-
rx: radiiPx[X] + 3,
|
|
33466
|
-
ry: radiiPx[Y] + 3
|
|
33467
|
-
}), /*#__PURE__*/React.createElement("ellipse", {
|
|
33468
|
-
className: "circle",
|
|
33469
|
-
cx: centerPx[X],
|
|
33470
|
-
cy: centerPx[Y],
|
|
33471
|
-
rx: radiiPx[X],
|
|
33472
|
-
ry: radiiPx[Y]
|
|
33473
|
-
}), /*#__PURE__*/React.createElement(DragHandle, {
|
|
33474
|
-
center: center
|
|
33475
|
-
}));
|
|
33476
|
-
}
|
|
33477
|
-
const dragHandleDimensions = [24, 14];
|
|
33478
|
-
const dragHandleDotPositions = crossProduct([-4.4, 0, 4.4], [-2.1, 2.1]);
|
|
33479
|
-
function DragHandle(props) {
|
|
33480
|
-
const {
|
|
33481
|
-
center
|
|
33482
|
-
} = props;
|
|
33483
|
-
const cornerRadius = Math.min(...dragHandleDimensions) / 2;
|
|
33484
|
-
const [centerPx] = useTransformVectorsToPixels(center);
|
|
33485
|
-
const topLeft = vec.sub(centerPx, vec.scale(dragHandleDimensions, 0.5));
|
|
33486
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("rect", {
|
|
33487
|
-
className: "movable-circle-handle",
|
|
33488
|
-
x: topLeft[X],
|
|
33489
|
-
y: topLeft[Y],
|
|
33490
|
-
width: dragHandleDimensions[X],
|
|
33491
|
-
height: dragHandleDimensions[Y],
|
|
33492
|
-
rx: cornerRadius,
|
|
33493
|
-
ry: cornerRadius
|
|
33494
|
-
}), dragHandleDotPositions.map(offsetPx => {
|
|
33495
|
-
const [xPx, yPx] = vec.add(offsetPx, centerPx);
|
|
33496
|
-
return /*#__PURE__*/React.createElement("circle", {
|
|
33497
|
-
key: `circle-${xPx}-${yPx}`,
|
|
33498
|
-
className: "movable-circle-handle-dot",
|
|
33499
|
-
cx: xPx,
|
|
33500
|
-
cy: yPx
|
|
33501
|
-
});
|
|
33502
|
-
}));
|
|
33503
|
-
}
|
|
33504
|
-
function crossProduct(as, bs) {
|
|
33505
|
-
const result = [];
|
|
33506
|
-
for (const a of as) {
|
|
33507
|
-
for (const b of bs) {
|
|
33508
|
-
result.push([a, b]);
|
|
33509
|
-
}
|
|
33510
|
-
}
|
|
33511
|
-
return result;
|
|
33877
|
+
function renderQuadraticGraph(state, dispatch) {
|
|
33878
|
+
return {
|
|
33879
|
+
graph: /*#__PURE__*/React.createElement(QuadraticGraph, {
|
|
33880
|
+
graphState: state,
|
|
33881
|
+
dispatch: dispatch
|
|
33882
|
+
}),
|
|
33883
|
+
interactiveElementsDescription: null
|
|
33884
|
+
};
|
|
33512
33885
|
}
|
|
33513
|
-
|
|
33514
33886
|
function QuadraticGraph(props) {
|
|
33515
33887
|
const {
|
|
33516
33888
|
dispatch,
|
|
@@ -33565,6 +33937,74 @@ const getQuadraticCoefficients$1 = coords => {
|
|
|
33565
33937
|
return [a, b, c];
|
|
33566
33938
|
};
|
|
33567
33939
|
|
|
33940
|
+
function renderRayGraph(state, dispatch) {
|
|
33941
|
+
return {
|
|
33942
|
+
graph: /*#__PURE__*/React.createElement(RayGraph, {
|
|
33943
|
+
graphState: state,
|
|
33944
|
+
dispatch: dispatch
|
|
33945
|
+
}),
|
|
33946
|
+
interactiveElementsDescription: null
|
|
33947
|
+
};
|
|
33948
|
+
}
|
|
33949
|
+
const RayGraph = props => {
|
|
33950
|
+
const {
|
|
33951
|
+
dispatch
|
|
33952
|
+
} = props;
|
|
33953
|
+
const {
|
|
33954
|
+
coords: line
|
|
33955
|
+
} = props.graphState;
|
|
33956
|
+
const handleMoveLine = delta => dispatch(actions.ray.moveRay(delta));
|
|
33957
|
+
const handleMovePoint = (pointIndex, newPoint) => dispatch(actions.ray.movePoint(pointIndex, newPoint));
|
|
33958
|
+
|
|
33959
|
+
// Ray graphs only have one line
|
|
33960
|
+
return /*#__PURE__*/React.createElement(MovableLine, {
|
|
33961
|
+
points: line,
|
|
33962
|
+
onMoveLine: handleMoveLine,
|
|
33963
|
+
onMovePoint: handleMovePoint,
|
|
33964
|
+
extend: {
|
|
33965
|
+
start: false,
|
|
33966
|
+
end: true
|
|
33967
|
+
}
|
|
33968
|
+
});
|
|
33969
|
+
};
|
|
33970
|
+
|
|
33971
|
+
function renderSegmentGraph(state, dispatch) {
|
|
33972
|
+
return {
|
|
33973
|
+
graph: /*#__PURE__*/React.createElement(SegmentGraph, {
|
|
33974
|
+
graphState: state,
|
|
33975
|
+
dispatch: dispatch
|
|
33976
|
+
}),
|
|
33977
|
+
interactiveElementsDescription: null
|
|
33978
|
+
};
|
|
33979
|
+
}
|
|
33980
|
+
const SegmentGraph = props => {
|
|
33981
|
+
const {
|
|
33982
|
+
dispatch
|
|
33983
|
+
} = props;
|
|
33984
|
+
const {
|
|
33985
|
+
coords: segments
|
|
33986
|
+
} = props.graphState;
|
|
33987
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, segments == null ? void 0 : segments.map((segment, i) => /*#__PURE__*/React.createElement(MovableLine, {
|
|
33988
|
+
key: i,
|
|
33989
|
+
points: segment,
|
|
33990
|
+
onMoveLine: delta => {
|
|
33991
|
+
dispatch(actions.segment.moveLine(i, delta));
|
|
33992
|
+
},
|
|
33993
|
+
onMovePoint: (endpointIndex, destination) => {
|
|
33994
|
+
dispatch(actions.segment.movePointInFigure(i, endpointIndex, destination));
|
|
33995
|
+
}
|
|
33996
|
+
})));
|
|
33997
|
+
};
|
|
33998
|
+
|
|
33999
|
+
function renderSinusoidGraph(state, dispatch) {
|
|
34000
|
+
return {
|
|
34001
|
+
graph: /*#__PURE__*/React.createElement(SinusoidGraph, {
|
|
34002
|
+
graphState: state,
|
|
34003
|
+
dispatch: dispatch
|
|
34004
|
+
}),
|
|
34005
|
+
interactiveElementsDescription: null
|
|
34006
|
+
};
|
|
34007
|
+
}
|
|
33568
34008
|
function SinusoidGraph(props) {
|
|
33569
34009
|
const {
|
|
33570
34010
|
dispatch,
|
|
@@ -33640,203 +34080,6 @@ const getSinusoidCoefficients$1 = coords => {
|
|
|
33640
34080
|
};
|
|
33641
34081
|
};
|
|
33642
34082
|
|
|
33643
|
-
function AngleGraph(props) {
|
|
33644
|
-
const {
|
|
33645
|
-
dispatch,
|
|
33646
|
-
graphState
|
|
33647
|
-
} = props;
|
|
33648
|
-
const {
|
|
33649
|
-
graphDimensionsInPixels
|
|
33650
|
-
} = useGraphConfig();
|
|
33651
|
-
const {
|
|
33652
|
-
coords,
|
|
33653
|
-
showAngles,
|
|
33654
|
-
range,
|
|
33655
|
-
allowReflexAngles,
|
|
33656
|
-
snapDegrees
|
|
33657
|
-
} = graphState;
|
|
33658
|
-
|
|
33659
|
-
// Break the coords into the two end points and the center point
|
|
33660
|
-
const endPoints = [coords[0], coords[2]];
|
|
33661
|
-
const centerPoint = coords[1];
|
|
33662
|
-
|
|
33663
|
-
// Convert the vectors to pixels for rendering the svg lines
|
|
33664
|
-
const angleLines = [[centerPoint, endPoints[0]], [centerPoint, endPoints[1]]];
|
|
33665
|
-
const linePixelCoords = [useTransformVectorsToPixels(centerPoint, endPoints[0]), useTransformVectorsToPixels(centerPoint, endPoints[1])];
|
|
33666
|
-
|
|
33667
|
-
// Create the SVG lines for the angle
|
|
33668
|
-
const svgLines = linePixelCoords.map(([startPtPx, endPtPx], i) => {
|
|
33669
|
-
const trimmedRange = trimRange(range, graphDimensionsInPixels);
|
|
33670
|
-
const endExtend = getIntersectionOfRayWithBox(angleLines[i][0], angleLines[i][1], trimmedRange);
|
|
33671
|
-
return /*#__PURE__*/React.createElement("g", {
|
|
33672
|
-
key: `line-${i}`
|
|
33673
|
-
}, /*#__PURE__*/React.createElement(SVGLine, {
|
|
33674
|
-
start: startPtPx,
|
|
33675
|
-
end: endPtPx,
|
|
33676
|
-
style: {
|
|
33677
|
-
stroke: "var(--movable-line-stroke-color)",
|
|
33678
|
-
strokeWidth: "var(--movable-line-stroke-weight)"
|
|
33679
|
-
}
|
|
33680
|
-
}), /*#__PURE__*/React.createElement(Vector, {
|
|
33681
|
-
tail: angleLines[i][1],
|
|
33682
|
-
tip: endExtend,
|
|
33683
|
-
color: "var(--movable-line-stroke-color)"
|
|
33684
|
-
}));
|
|
33685
|
-
});
|
|
33686
|
-
|
|
33687
|
-
// Create the angle indicator parameters
|
|
33688
|
-
const angleParams = {
|
|
33689
|
-
vertex: centerPoint,
|
|
33690
|
-
coords: endPoints,
|
|
33691
|
-
allowReflexAngles: allowReflexAngles || false,
|
|
33692
|
-
// Whether to allow reflex angles or not
|
|
33693
|
-
snapDegrees: snapDegrees || 1,
|
|
33694
|
-
// The multiple of degrees to snap to
|
|
33695
|
-
range: range,
|
|
33696
|
-
showAngles: showAngles || false // Whether to show the angle or not
|
|
33697
|
-
};
|
|
33698
|
-
|
|
33699
|
-
// Render the lines, angle, and then movable points
|
|
33700
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, svgLines, /*#__PURE__*/React.createElement(Angle, angleParams), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33701
|
-
point: coords[1],
|
|
33702
|
-
constrain: p => p,
|
|
33703
|
-
onMove: destination => dispatch(actions.angle.movePoint(1, destination))
|
|
33704
|
-
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33705
|
-
point: coords[0],
|
|
33706
|
-
constrain: getAngleSideConstraint(coords[0], coords[1], snapDegrees || 1),
|
|
33707
|
-
onMove: destination => dispatch(actions.angle.movePoint(0, destination))
|
|
33708
|
-
}), /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33709
|
-
point: coords[2],
|
|
33710
|
-
constrain: getAngleSideConstraint(coords[2], coords[1], snapDegrees || 1),
|
|
33711
|
-
onMove: destination => dispatch(actions.angle.movePoint(2, destination))
|
|
33712
|
-
}));
|
|
33713
|
-
}
|
|
33714
|
-
const positiveX = [1, 0];
|
|
33715
|
-
const negativeX = [-1, 0];
|
|
33716
|
-
const positiveY = [0, 1];
|
|
33717
|
-
const negativeY = [0, -1];
|
|
33718
|
-
function getAngleSideConstraint(sidePoint, vertex, snapDegrees) {
|
|
33719
|
-
var _findIntersectionOfRa, _findIntersectionOfRa2, _findIntersectionOfRa3, _findIntersectionOfRa4;
|
|
33720
|
-
const currentAngle = calculateAngleInDegrees(vec.sub(sidePoint, vertex));
|
|
33721
|
-
|
|
33722
|
-
// Find the rays that start at the current point and point up, down, left
|
|
33723
|
-
// and right.
|
|
33724
|
-
const leftRay = [sidePoint, vec.add(sidePoint, negativeX)];
|
|
33725
|
-
const rightRay = [sidePoint, vec.add(sidePoint, positiveX)];
|
|
33726
|
-
const upRay = [sidePoint, vec.add(sidePoint, positiveY)];
|
|
33727
|
-
const downRay = [sidePoint, vec.add(sidePoint, negativeY)];
|
|
33728
|
-
|
|
33729
|
-
// find the angles that lie one snap step clockwise and counter-clockwise
|
|
33730
|
-
// from the current angle. These are the angles to which the side can be
|
|
33731
|
-
// moved.
|
|
33732
|
-
const oneStepCounterClockwise = currentAngle + snapDegrees;
|
|
33733
|
-
const oneStepClockwise = currentAngle - snapDegrees;
|
|
33734
|
-
|
|
33735
|
-
// find the rays that start from the vertex and point in the direction of
|
|
33736
|
-
// the angles we just computed.
|
|
33737
|
-
const counterClockwiseRay = [vertex, vec.add(vertex, polar(1, oneStepCounterClockwise))];
|
|
33738
|
-
const clockwiseRay = [vertex, vec.add(vertex, polar(1, oneStepClockwise))];
|
|
33739
|
-
|
|
33740
|
-
// find the intersections of those rays with the horizontal and vertical
|
|
33741
|
-
// rays extending from the sidePoint. These intersections are the points to
|
|
33742
|
-
// which sidePoint can move that will result in a rotation of `snapDegrees`.
|
|
33743
|
-
const left = (_findIntersectionOfRa = findIntersectionOfRays(leftRay, counterClockwiseRay)) != null ? _findIntersectionOfRa : findIntersectionOfRays(leftRay, clockwiseRay);
|
|
33744
|
-
const right = (_findIntersectionOfRa2 = findIntersectionOfRays(rightRay, counterClockwiseRay)) != null ? _findIntersectionOfRa2 : findIntersectionOfRays(rightRay, clockwiseRay);
|
|
33745
|
-
const up = (_findIntersectionOfRa3 = findIntersectionOfRays(upRay, counterClockwiseRay)) != null ? _findIntersectionOfRa3 : findIntersectionOfRays(upRay, clockwiseRay);
|
|
33746
|
-
const down = (_findIntersectionOfRa4 = findIntersectionOfRays(downRay, counterClockwiseRay)) != null ? _findIntersectionOfRa4 : findIntersectionOfRays(downRay, clockwiseRay);
|
|
33747
|
-
return {
|
|
33748
|
-
up: up != null ? up : sidePoint,
|
|
33749
|
-
down: down != null ? down : sidePoint,
|
|
33750
|
-
left: left != null ? left : sidePoint,
|
|
33751
|
-
right: right != null ? right : sidePoint
|
|
33752
|
-
};
|
|
33753
|
-
}
|
|
33754
|
-
|
|
33755
|
-
function LimitedPointGraph(props) {
|
|
33756
|
-
const {
|
|
33757
|
-
dispatch
|
|
33758
|
-
} = props;
|
|
33759
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, props.graphState.coords.map((point, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33760
|
-
key: i,
|
|
33761
|
-
point: point,
|
|
33762
|
-
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination))
|
|
33763
|
-
})));
|
|
33764
|
-
}
|
|
33765
|
-
function UnlimitedPointGraph(props) {
|
|
33766
|
-
const {
|
|
33767
|
-
dispatch
|
|
33768
|
-
} = props;
|
|
33769
|
-
const graphState = useGraphConfig();
|
|
33770
|
-
const {
|
|
33771
|
-
range: [[minX, maxX], [minY, maxY]]
|
|
33772
|
-
} = graphState;
|
|
33773
|
-
const width = maxX - minX;
|
|
33774
|
-
const height = maxY - minY;
|
|
33775
|
-
const [[widthPx, heightPx]] = useTransformDimensionsToPixels([width, height]);
|
|
33776
|
-
const [[left, top]] = useTransformVectorsToPixels([minX, maxY]);
|
|
33777
|
-
const itemsRef = React.useRef([]);
|
|
33778
|
-
React.useEffect(() => {
|
|
33779
|
-
const focusedIndex = props.graphState.focusedPointIndex;
|
|
33780
|
-
if (focusedIndex != null) {
|
|
33781
|
-
var _itemsRef$current$foc;
|
|
33782
|
-
(_itemsRef$current$foc = itemsRef.current[focusedIndex]) == null || _itemsRef$current$foc.focus();
|
|
33783
|
-
}
|
|
33784
|
-
}, [props.graphState.focusedPointIndex, itemsRef]);
|
|
33785
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("rect", {
|
|
33786
|
-
style: {
|
|
33787
|
-
fill: "rgba(0,0,0,0)",
|
|
33788
|
-
cursor: "crosshair"
|
|
33789
|
-
},
|
|
33790
|
-
width: widthPx,
|
|
33791
|
-
height: heightPx,
|
|
33792
|
-
x: left,
|
|
33793
|
-
y: top,
|
|
33794
|
-
onClick: event => {
|
|
33795
|
-
const elementRect = event.currentTarget.getBoundingClientRect();
|
|
33796
|
-
const x = event.clientX - elementRect.x;
|
|
33797
|
-
const y = event.clientY - elementRect.y;
|
|
33798
|
-
const graphCoordinates = pixelsToVectors([[x, y]], graphState);
|
|
33799
|
-
dispatch(actions.pointGraph.addPoint(graphCoordinates[0]));
|
|
33800
|
-
}
|
|
33801
|
-
}), props.graphState.coords.map((point, i) => /*#__PURE__*/React.createElement(MovablePoint$1, {
|
|
33802
|
-
key: i,
|
|
33803
|
-
point: point,
|
|
33804
|
-
onMove: destination => dispatch(actions.pointGraph.movePoint(i, destination)),
|
|
33805
|
-
ref: ref => {
|
|
33806
|
-
itemsRef.current[i] = ref;
|
|
33807
|
-
},
|
|
33808
|
-
onFocusChange: (event, isFocused) => {
|
|
33809
|
-
if (isFocused) {
|
|
33810
|
-
dispatch(actions.pointGraph.focusPoint(i));
|
|
33811
|
-
} else {
|
|
33812
|
-
var _event$relatedTarget, _event$relatedTarget2;
|
|
33813
|
-
if (((_event$relatedTarget = event.relatedTarget) == null ? void 0 : _event$relatedTarget.id) === REMOVE_BUTTON_ID) {
|
|
33814
|
-
return;
|
|
33815
|
-
// This is an optimization: If the next target
|
|
33816
|
-
// is a point then don't blur because it casues
|
|
33817
|
-
// the remove button to get taken off the page
|
|
33818
|
-
// and then put back on The new point will
|
|
33819
|
-
// receive focus and set the correct state in
|
|
33820
|
-
// the reducer
|
|
33821
|
-
} else if ((_event$relatedTarget2 = event.relatedTarget) != null && _event$relatedTarget2.classList.contains("movable-point")) {
|
|
33822
|
-
return;
|
|
33823
|
-
}
|
|
33824
|
-
dispatch(actions.pointGraph.blurPoint());
|
|
33825
|
-
}
|
|
33826
|
-
},
|
|
33827
|
-
onClick: () => {
|
|
33828
|
-
dispatch(actions.pointGraph.clickPoint(i));
|
|
33829
|
-
}
|
|
33830
|
-
})));
|
|
33831
|
-
}
|
|
33832
|
-
function PointGraph(props) {
|
|
33833
|
-
const numPoints = props.graphState.numPoints;
|
|
33834
|
-
if (numPoints === "unlimited") {
|
|
33835
|
-
return UnlimitedPointGraph(props);
|
|
33836
|
-
}
|
|
33837
|
-
return LimitedPointGraph(props);
|
|
33838
|
-
}
|
|
33839
|
-
|
|
33840
34083
|
const protractorImage = "https://ka-perseus-graphie.s3.amazonaws.com/e9d032f2ab8b95979f674fbfa67056442ba1ff6a.png";
|
|
33841
34084
|
|
|
33842
34085
|
// The vector from the center of the protractor to the top left corner of the
|
|
@@ -33984,7 +34227,6 @@ function useDraggablePx(args) {
|
|
|
33984
34227
|
* - Protractor
|
|
33985
34228
|
* - Interactive Graph Elements
|
|
33986
34229
|
*/
|
|
33987
|
-
const REMOVE_BUTTON_ID = "perseus_mafs_remove_button";
|
|
33988
34230
|
const MafsGraph = props => {
|
|
33989
34231
|
var _props$flags;
|
|
33990
34232
|
const {
|
|
@@ -34002,6 +34244,7 @@ const MafsGraph = props => {
|
|
|
34002
34244
|
const tickStep = props.step;
|
|
34003
34245
|
const uniqueId = React.useId();
|
|
34004
34246
|
const descriptionId = `interactive-graph-description-${uniqueId}`;
|
|
34247
|
+
const interactiveElementsDescriptionId = `interactive-graph-interactive-elements-description-${uniqueId}`;
|
|
34005
34248
|
const graphRef = React.useRef(null);
|
|
34006
34249
|
const {
|
|
34007
34250
|
analytics
|
|
@@ -34025,6 +34268,7 @@ const MafsGraph = props => {
|
|
|
34025
34268
|
const {
|
|
34026
34269
|
strings
|
|
34027
34270
|
} = usePerseusI18n();
|
|
34271
|
+
const interactionPrompt = isUnlimitedGraphState(state) && state.showKeyboardInteractionInvitation;
|
|
34028
34272
|
useOnMountEffect(() => {
|
|
34029
34273
|
analytics.onAnalyticsEvent({
|
|
34030
34274
|
type: "perseus:interactive-graph-widget:rendered",
|
|
@@ -34035,6 +34279,13 @@ const MafsGraph = props => {
|
|
|
34035
34279
|
}
|
|
34036
34280
|
});
|
|
34037
34281
|
});
|
|
34282
|
+
const {
|
|
34283
|
+
graph,
|
|
34284
|
+
interactiveElementsDescription
|
|
34285
|
+
} = renderGraphElements({
|
|
34286
|
+
state,
|
|
34287
|
+
dispatch
|
|
34288
|
+
});
|
|
34038
34289
|
return /*#__PURE__*/React.createElement(GraphConfigContext.Provider, {
|
|
34039
34290
|
value: {
|
|
34040
34291
|
range: state.range,
|
|
@@ -34066,7 +34317,7 @@ const MafsGraph = props => {
|
|
|
34066
34317
|
handleKeyboardEvent(event, state, dispatch);
|
|
34067
34318
|
},
|
|
34068
34319
|
"aria-label": fullGraphAriaLabel,
|
|
34069
|
-
"aria-describedby": fullGraphAriaDescription
|
|
34320
|
+
"aria-describedby": describedByIds(fullGraphAriaDescription && descriptionId, interactiveElementsDescription && interactiveElementsDescriptionId),
|
|
34070
34321
|
ref: graphRef,
|
|
34071
34322
|
tabIndex: 0,
|
|
34072
34323
|
onFocus: event => {
|
|
@@ -34078,12 +34329,12 @@ const MafsGraph = props => {
|
|
|
34078
34329
|
}, fullGraphAriaDescription && /*#__PURE__*/React.createElement(View, {
|
|
34079
34330
|
id: descriptionId,
|
|
34080
34331
|
tabIndex: -1,
|
|
34081
|
-
|
|
34082
|
-
|
|
34083
|
-
|
|
34084
|
-
|
|
34085
|
-
|
|
34086
|
-
},
|
|
34332
|
+
className: "mafs-sr-only"
|
|
34333
|
+
}, fullGraphAriaDescription), interactiveElementsDescription && /*#__PURE__*/React.createElement(View, {
|
|
34334
|
+
id: interactiveElementsDescriptionId,
|
|
34335
|
+
tabIndex: -1,
|
|
34336
|
+
className: "mafs-sr-only"
|
|
34337
|
+
}, interactiveElementsDescription), /*#__PURE__*/React.createElement(LegacyGrid, {
|
|
34087
34338
|
box: props.box,
|
|
34088
34339
|
backgroundImage: props.backgroundImage
|
|
34089
34340
|
}), /*#__PURE__*/React.createElement(View, {
|
|
@@ -34134,10 +34385,7 @@ const MafsGraph = props => {
|
|
|
34134
34385
|
zoom: false,
|
|
34135
34386
|
width: width,
|
|
34136
34387
|
height: height
|
|
34137
|
-
}, /*#__PURE__*/React.createElement("svg", nestedSVGAttributes, props.showProtractor && /*#__PURE__*/React.createElement(Protractor, null),
|
|
34138
|
-
state,
|
|
34139
|
-
dispatch
|
|
34140
|
-
}))))), state.type === "point" && state.showKeyboardInteractionInvitation && /*#__PURE__*/React.createElement(View, {
|
|
34388
|
+
}, /*#__PURE__*/React.createElement("svg", nestedSVGAttributes, props.showProtractor && /*#__PURE__*/React.createElement(Protractor, null), graph)))), interactionPrompt && /*#__PURE__*/React.createElement(View, {
|
|
34141
34389
|
style: {
|
|
34142
34390
|
textAlign: "center",
|
|
34143
34391
|
backgroundColor: "white",
|
|
@@ -34154,7 +34402,7 @@ const MafsGraph = props => {
|
|
|
34154
34402
|
state,
|
|
34155
34403
|
dispatch,
|
|
34156
34404
|
width,
|
|
34157
|
-
strings
|
|
34405
|
+
perseusStrings: strings
|
|
34158
34406
|
})));
|
|
34159
34407
|
};
|
|
34160
34408
|
const renderPointGraphControls = props => {
|
|
@@ -34164,7 +34412,7 @@ const renderPointGraphControls = props => {
|
|
|
34164
34412
|
focusedPointIndex
|
|
34165
34413
|
} = props.state;
|
|
34166
34414
|
const {
|
|
34167
|
-
|
|
34415
|
+
perseusStrings
|
|
34168
34416
|
} = props;
|
|
34169
34417
|
const shouldShowRemoveButton = showRemovePointButton && focusedPointIndex !== null;
|
|
34170
34418
|
return /*#__PURE__*/React.createElement(View, {
|
|
@@ -34182,7 +34430,7 @@ const renderPointGraphControls = props => {
|
|
|
34182
34430
|
onClick: () => {
|
|
34183
34431
|
props.dispatch(actions.pointGraph.addPoint([0, 0]));
|
|
34184
34432
|
}
|
|
34185
|
-
},
|
|
34433
|
+
}, perseusStrings.addPoint), interactionMode === "mouse" && /*#__PURE__*/React.createElement(Button, {
|
|
34186
34434
|
id: REMOVE_BUTTON_ID,
|
|
34187
34435
|
kind: "secondary",
|
|
34188
34436
|
color: "destructive"
|
|
@@ -34195,17 +34443,66 @@ const renderPointGraphControls = props => {
|
|
|
34195
34443
|
marginLeft: "20px",
|
|
34196
34444
|
visibility: shouldShowRemoveButton ? "visible" : "hidden"
|
|
34197
34445
|
},
|
|
34198
|
-
onClick:
|
|
34446
|
+
onClick: _event => {
|
|
34199
34447
|
props.dispatch(actions.pointGraph.removePoint(props.state.focusedPointIndex));
|
|
34200
34448
|
}
|
|
34201
|
-
},
|
|
34449
|
+
}, perseusStrings.removePoint));
|
|
34450
|
+
};
|
|
34451
|
+
|
|
34452
|
+
/**
|
|
34453
|
+
* TODO(catjohnson): The polygon controls will be vastly different from the point controls.
|
|
34454
|
+
* Will be keeping this function as is for the time being, even if it's a copy of the point graph
|
|
34455
|
+
* controls.
|
|
34456
|
+
*/
|
|
34457
|
+
const renderPolygonGraphControls = props => {
|
|
34458
|
+
const {
|
|
34459
|
+
interactionMode,
|
|
34460
|
+
showRemovePointButton,
|
|
34461
|
+
focusedPointIndex
|
|
34462
|
+
} = props.state;
|
|
34463
|
+
const {
|
|
34464
|
+
perseusStrings
|
|
34465
|
+
} = props;
|
|
34466
|
+
const shouldShowRemoveButton = showRemovePointButton && focusedPointIndex !== null;
|
|
34467
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
34468
|
+
style: {
|
|
34469
|
+
flexDirection: "row",
|
|
34470
|
+
width: props.width
|
|
34471
|
+
}
|
|
34472
|
+
}, interactionMode === "keyboard" && /*#__PURE__*/React.createElement(Button, {
|
|
34473
|
+
kind: "secondary",
|
|
34474
|
+
style: {
|
|
34475
|
+
width: "100%",
|
|
34476
|
+
marginLeft: "20px"
|
|
34477
|
+
},
|
|
34478
|
+
tabIndex: 0,
|
|
34479
|
+
onClick: () => {
|
|
34480
|
+
props.dispatch(actions.polygon.addPoint([0, 0]));
|
|
34481
|
+
}
|
|
34482
|
+
}, perseusStrings.addPoint), interactionMode === "mouse" && /*#__PURE__*/React.createElement(Button, {
|
|
34483
|
+
id: REMOVE_BUTTON_ID,
|
|
34484
|
+
kind: "secondary",
|
|
34485
|
+
color: "destructive"
|
|
34486
|
+
// This button is meant to be interacted with by the mouse only
|
|
34487
|
+
// Never allow learners to tab to this button
|
|
34488
|
+
,
|
|
34489
|
+
tabIndex: -1,
|
|
34490
|
+
style: {
|
|
34491
|
+
width: "100%",
|
|
34492
|
+
marginLeft: "20px",
|
|
34493
|
+
visibility: shouldShowRemoveButton ? "visible" : "hidden"
|
|
34494
|
+
},
|
|
34495
|
+
onClick: _event => {
|
|
34496
|
+
props.dispatch(actions.polygon.removePoint(props.state.focusedPointIndex));
|
|
34497
|
+
}
|
|
34498
|
+
}, perseusStrings.removePoint));
|
|
34202
34499
|
};
|
|
34203
34500
|
const renderGraphControls = props => {
|
|
34204
34501
|
const {
|
|
34205
34502
|
state,
|
|
34206
34503
|
dispatch,
|
|
34207
34504
|
width,
|
|
34208
|
-
|
|
34505
|
+
perseusStrings
|
|
34209
34506
|
} = props;
|
|
34210
34507
|
const {
|
|
34211
34508
|
type
|
|
@@ -34217,7 +34514,17 @@ const renderGraphControls = props => {
|
|
|
34217
34514
|
state,
|
|
34218
34515
|
dispatch,
|
|
34219
34516
|
width,
|
|
34220
|
-
|
|
34517
|
+
perseusStrings
|
|
34518
|
+
});
|
|
34519
|
+
}
|
|
34520
|
+
return null;
|
|
34521
|
+
case "polygon":
|
|
34522
|
+
if (state.numSides === "unlimited") {
|
|
34523
|
+
return renderPolygonGraphControls({
|
|
34524
|
+
state,
|
|
34525
|
+
dispatch,
|
|
34526
|
+
width,
|
|
34527
|
+
perseusStrings
|
|
34221
34528
|
});
|
|
34222
34529
|
}
|
|
34223
34530
|
return null;
|
|
@@ -34226,21 +34533,29 @@ const renderGraphControls = props => {
|
|
|
34226
34533
|
}
|
|
34227
34534
|
};
|
|
34228
34535
|
function handleFocusEvent(event, state, dispatch) {
|
|
34229
|
-
if (state
|
|
34536
|
+
if (isUnlimitedGraphState(state)) {
|
|
34230
34537
|
if (event.target.classList.contains("mafs-graph") && state.interactionMode === "mouse") {
|
|
34231
34538
|
dispatch(actions.global.changeKeyboardInvitationVisibility(true));
|
|
34232
34539
|
}
|
|
34233
34540
|
}
|
|
34234
34541
|
}
|
|
34235
|
-
function handleBlurEvent(
|
|
34236
|
-
if (state
|
|
34542
|
+
function handleBlurEvent(_event, state, dispatch) {
|
|
34543
|
+
if (isUnlimitedGraphState(state)) {
|
|
34237
34544
|
dispatch(actions.global.changeKeyboardInvitationVisibility(false));
|
|
34238
34545
|
}
|
|
34239
34546
|
}
|
|
34240
34547
|
function handleKeyboardEvent(event, state, dispatch) {
|
|
34241
|
-
if (state
|
|
34548
|
+
if (isUnlimitedGraphState(state)) {
|
|
34242
34549
|
if (event.key === "Backspace") {
|
|
34243
|
-
|
|
34550
|
+
var _document$activeEleme;
|
|
34551
|
+
// TODO(benchristel): Checking classList here is a hack to prevent
|
|
34552
|
+
// points from being deleted if the user presses the backspace key
|
|
34553
|
+
// while the whole graph is focused. Instead of doing this, we
|
|
34554
|
+
// should move the keyboard event handler to the movable point
|
|
34555
|
+
// handle element.
|
|
34556
|
+
if ((_document$activeEleme = document.activeElement) != null && _document$activeEleme.classList.contains("movable-point__focusable-handle")) {
|
|
34557
|
+
dispatch(actions.global.deleteIntent());
|
|
34558
|
+
}
|
|
34244
34559
|
|
|
34245
34560
|
// After removing a point blur
|
|
34246
34561
|
// It would be nice if this could focus on the graph but doing so
|
|
@@ -34303,7 +34618,7 @@ const calculateNestedSVGCoords = (range, width, height) => {
|
|
|
34303
34618
|
viewboxY
|
|
34304
34619
|
};
|
|
34305
34620
|
};
|
|
34306
|
-
const
|
|
34621
|
+
const renderGraphElements = props => {
|
|
34307
34622
|
const {
|
|
34308
34623
|
state,
|
|
34309
34624
|
dispatch
|
|
@@ -34313,62 +34628,41 @@ const renderGraph = props => {
|
|
|
34313
34628
|
} = state;
|
|
34314
34629
|
switch (type) {
|
|
34315
34630
|
case "angle":
|
|
34316
|
-
return
|
|
34317
|
-
graphState: state,
|
|
34318
|
-
dispatch: dispatch
|
|
34319
|
-
});
|
|
34631
|
+
return renderAngleGraph(state, dispatch);
|
|
34320
34632
|
case "segment":
|
|
34321
|
-
return
|
|
34322
|
-
graphState: state,
|
|
34323
|
-
dispatch: dispatch
|
|
34324
|
-
});
|
|
34633
|
+
return renderSegmentGraph(state, dispatch);
|
|
34325
34634
|
case "linear-system":
|
|
34326
|
-
return
|
|
34327
|
-
graphState: state,
|
|
34328
|
-
dispatch: dispatch
|
|
34329
|
-
});
|
|
34635
|
+
return renderLinearSystemGraph(state, dispatch);
|
|
34330
34636
|
case "linear":
|
|
34331
|
-
return
|
|
34332
|
-
graphState: state,
|
|
34333
|
-
dispatch: dispatch
|
|
34334
|
-
});
|
|
34637
|
+
return renderLinearGraph(state, dispatch);
|
|
34335
34638
|
case "ray":
|
|
34336
|
-
return
|
|
34337
|
-
graphState: state,
|
|
34338
|
-
dispatch: dispatch
|
|
34339
|
-
});
|
|
34639
|
+
return renderRayGraph(state, dispatch);
|
|
34340
34640
|
case "polygon":
|
|
34341
|
-
return
|
|
34342
|
-
graphState: state,
|
|
34343
|
-
dispatch: dispatch
|
|
34344
|
-
});
|
|
34641
|
+
return renderPolygonGraph(state, dispatch);
|
|
34345
34642
|
case "point":
|
|
34346
|
-
return
|
|
34347
|
-
graphState: state,
|
|
34348
|
-
dispatch: dispatch
|
|
34349
|
-
});
|
|
34643
|
+
return renderPointGraph(state, dispatch);
|
|
34350
34644
|
case "circle":
|
|
34351
|
-
return
|
|
34352
|
-
graphState: state,
|
|
34353
|
-
dispatch: dispatch
|
|
34354
|
-
});
|
|
34645
|
+
return renderCircleGraph(state, dispatch);
|
|
34355
34646
|
case "quadratic":
|
|
34356
|
-
return
|
|
34357
|
-
graphState: state,
|
|
34358
|
-
dispatch: dispatch
|
|
34359
|
-
});
|
|
34647
|
+
return renderQuadraticGraph(state, dispatch);
|
|
34360
34648
|
case "sinusoid":
|
|
34361
|
-
return
|
|
34362
|
-
graphState: state,
|
|
34363
|
-
dispatch: dispatch
|
|
34364
|
-
});
|
|
34649
|
+
return renderSinusoidGraph(state, dispatch);
|
|
34365
34650
|
case "none":
|
|
34366
|
-
return
|
|
34651
|
+
return {
|
|
34652
|
+
graph: null,
|
|
34653
|
+
interactiveElementsDescription: null
|
|
34654
|
+
};
|
|
34367
34655
|
default:
|
|
34368
34656
|
throw new UnreachableCaseError(type);
|
|
34369
34657
|
}
|
|
34370
34658
|
};
|
|
34371
34659
|
|
|
34660
|
+
// Returns a space-separated string like "foo bar" given several optional
|
|
34661
|
+
// string IDs. If all args are falsy, returns undefined.
|
|
34662
|
+
function describedByIds(...args) {
|
|
34663
|
+
return args.filter(Boolean).join(" ") || undefined;
|
|
34664
|
+
}
|
|
34665
|
+
|
|
34372
34666
|
// Converts the state of a StatefulMafsGraph back to the format used to
|
|
34373
34667
|
// represent graph state in the widget JSON.
|
|
34374
34668
|
//
|
|
@@ -34483,10 +34777,15 @@ function initializeGraphState(params) {
|
|
|
34483
34777
|
case "polygon":
|
|
34484
34778
|
return _extends({}, shared, {
|
|
34485
34779
|
type: "polygon",
|
|
34780
|
+
numSides: graph.numSides || 0,
|
|
34486
34781
|
showAngles: Boolean(graph.showAngles),
|
|
34487
34782
|
showSides: Boolean(graph.showSides),
|
|
34488
34783
|
coords: getPolygonCoords(graph, range, step),
|
|
34489
|
-
snapTo: (_graph$snapTo = graph.snapTo) != null ? _graph$snapTo : "grid"
|
|
34784
|
+
snapTo: (_graph$snapTo = graph.snapTo) != null ? _graph$snapTo : "grid",
|
|
34785
|
+
focusedPointIndex: null,
|
|
34786
|
+
showRemovePointButton: false,
|
|
34787
|
+
interactionMode: "mouse",
|
|
34788
|
+
showKeyboardInteractionInvitation: false
|
|
34490
34789
|
});
|
|
34491
34790
|
case "point":
|
|
34492
34791
|
return _extends({}, shared, {
|
|
@@ -34776,10 +35075,9 @@ function interactiveGraphReducer(state, action) {
|
|
|
34776
35075
|
}
|
|
34777
35076
|
function doDeleteIntent(state, action) {
|
|
34778
35077
|
// For unlimited point graphs
|
|
34779
|
-
if (state
|
|
34780
|
-
//
|
|
35078
|
+
if (isUnlimitedGraphState(state)) {
|
|
35079
|
+
// Remove the last point that was focused, if any
|
|
34781
35080
|
if (state.focusedPointIndex !== null) {
|
|
34782
|
-
// Remove the focused focus
|
|
34783
35081
|
return doRemovePoint(state, actions.pointGraph.removePoint(state.focusedPointIndex));
|
|
34784
35082
|
}
|
|
34785
35083
|
}
|
|
@@ -34787,6 +35085,7 @@ function doDeleteIntent(state, action) {
|
|
|
34787
35085
|
}
|
|
34788
35086
|
function doFocusPoint(state, action) {
|
|
34789
35087
|
switch (state.type) {
|
|
35088
|
+
case "polygon":
|
|
34790
35089
|
case "point":
|
|
34791
35090
|
return _extends({}, state, {
|
|
34792
35091
|
focusedPointIndex: action.index
|
|
@@ -34797,6 +35096,7 @@ function doFocusPoint(state, action) {
|
|
|
34797
35096
|
}
|
|
34798
35097
|
function doBlurPoint(state, action) {
|
|
34799
35098
|
switch (state.type) {
|
|
35099
|
+
case "polygon":
|
|
34800
35100
|
case "point":
|
|
34801
35101
|
const nextState = _extends({}, state, {
|
|
34802
35102
|
showRemovePointButton: false
|
|
@@ -34810,10 +35110,7 @@ function doBlurPoint(state, action) {
|
|
|
34810
35110
|
}
|
|
34811
35111
|
}
|
|
34812
35112
|
function doClickPoint(state, action) {
|
|
34813
|
-
if (state
|
|
34814
|
-
return state;
|
|
34815
|
-
}
|
|
34816
|
-
if (state.numPoints === "unlimited") {
|
|
35113
|
+
if (isUnlimitedGraphState(state)) {
|
|
34817
35114
|
return _extends({}, state, {
|
|
34818
35115
|
focusedPointIndex: action.index,
|
|
34819
35116
|
showRemovePointButton: true
|
|
@@ -34822,10 +35119,7 @@ function doClickPoint(state, action) {
|
|
|
34822
35119
|
return state;
|
|
34823
35120
|
}
|
|
34824
35121
|
function doChangeInteractionMode(state, action) {
|
|
34825
|
-
if (state
|
|
34826
|
-
return state;
|
|
34827
|
-
}
|
|
34828
|
-
if (state.numPoints === "unlimited") {
|
|
35122
|
+
if (isUnlimitedGraphState(state)) {
|
|
34829
35123
|
const nextKeyboardInvitation = action.mode === "keyboard" ? false : state.showKeyboardInteractionInvitation;
|
|
34830
35124
|
return _extends({}, state, {
|
|
34831
35125
|
interactionMode: action.mode,
|
|
@@ -34835,10 +35129,7 @@ function doChangeInteractionMode(state, action) {
|
|
|
34835
35129
|
return state;
|
|
34836
35130
|
}
|
|
34837
35131
|
function doChangeKeyboardInvitationVisibility(state, action) {
|
|
34838
|
-
if (state
|
|
34839
|
-
return state;
|
|
34840
|
-
}
|
|
34841
|
-
if (state.numPoints === "unlimited") {
|
|
35132
|
+
if (isUnlimitedGraphState(state)) {
|
|
34842
35133
|
return _extends({}, state, {
|
|
34843
35134
|
showKeyboardInteractionInvitation: action.shouldShow,
|
|
34844
35135
|
hasBeenInteractedWith: true
|
|
@@ -35169,7 +35460,7 @@ function doChangeRange(state, action) {
|
|
|
35169
35460
|
});
|
|
35170
35461
|
}
|
|
35171
35462
|
function doAddPoint(state, action) {
|
|
35172
|
-
if (state
|
|
35463
|
+
if (!isUnlimitedGraphState(state)) {
|
|
35173
35464
|
return state;
|
|
35174
35465
|
}
|
|
35175
35466
|
const {
|
|
@@ -35193,7 +35484,7 @@ function doAddPoint(state, action) {
|
|
|
35193
35484
|
});
|
|
35194
35485
|
}
|
|
35195
35486
|
function doRemovePoint(state, action) {
|
|
35196
|
-
if (state
|
|
35487
|
+
if (!isUnlimitedGraphState(state)) {
|
|
35197
35488
|
return state;
|
|
35198
35489
|
}
|
|
35199
35490
|
let nextFocusedPointIndex;
|
|
@@ -37499,9 +37790,6 @@ function shouldUseMafs(mafsFlags, graph) {
|
|
|
37499
37790
|
return Boolean(mafsFlags["point"]);
|
|
37500
37791
|
case "polygon":
|
|
37501
37792
|
if (graph.numSides === UNLIMITED) {
|
|
37502
|
-
// TODO(benchristel): add a feature flag for the "unlimited"
|
|
37503
|
-
// case once we've implemented polygon graphs with unlimited
|
|
37504
|
-
// sides
|
|
37505
37793
|
return Boolean(mafsFlags["unlimited-polygon"]);
|
|
37506
37794
|
}
|
|
37507
37795
|
return Boolean(mafsFlags["polygon"]);
|
|
@@ -37519,974 +37807,15 @@ var InteractiveGraph$1 = {
|
|
|
37519
37807
|
validator: interactiveGraphValidator
|
|
37520
37808
|
};
|
|
37521
37809
|
|
|
37522
|
-
|
|
37523
|
-
const
|
|
37524
|
-
|
|
37525
|
-
const gray = "#999999";
|
|
37526
|
-
const grayLight = "#AAAAAA";
|
|
37527
|
-
const grayLighter = "#DDDDDD";
|
|
37528
|
-
const white = "#FFFFFF";
|
|
37529
|
-
const blue = "#005A88";
|
|
37530
|
-
const blueDark = "#2C3747";
|
|
37531
|
-
const green = "#76A005";
|
|
37532
|
-
const red = "#CF5044";
|
|
37533
|
-
const yellow = "#FFC40D";
|
|
37534
|
-
const orange = "#BF4F04";
|
|
37535
|
-
const pink = "#C3325F";
|
|
37536
|
-
const purple = "#7A43B6";
|
|
37537
|
-
const bodyBackground = "#FFFFFF";
|
|
37538
|
-
const textColor = "#444444";
|
|
37539
|
-
const linkColor = "#005987";
|
|
37540
|
-
const linkColorHover = "#678D00";
|
|
37541
|
-
const sansFontFamily = "'Helvetica Neue',Helvetica,Arial,sans-serif";
|
|
37542
|
-
const serifFontFamily = "Georgia,'Times New Roman',Times,serif";
|
|
37543
|
-
const monoFontFamily = "Monaco,Menlo,Consolas,'Courier New',monospace";
|
|
37544
|
-
const baseFontSize = "14px";
|
|
37545
|
-
const baseFontFamily = "inherit";
|
|
37546
|
-
const baseLineHeight = "20px";
|
|
37547
|
-
const altFontFamily = "Georgia,'Times New Roman',Times,serif";
|
|
37548
|
-
const headingsFontFamily = "inherit";
|
|
37549
|
-
const headingsFontWeight = "bold";
|
|
37550
|
-
const headingsColor = "inherit";
|
|
37551
|
-
const fontSizeLarge = "18px";
|
|
37552
|
-
const fontSizeSmall = "12px";
|
|
37553
|
-
const fontSizeMini = "10.5px";
|
|
37554
|
-
const paddingLarge = "11px 19px";
|
|
37555
|
-
const paddingSmall = "2px 10px";
|
|
37556
|
-
const paddingMini = "0 6px";
|
|
37557
|
-
const baseBorderRadius = "4px";
|
|
37558
|
-
const borderRadiusLarge = "6px";
|
|
37559
|
-
const borderRadiusSmall = "3px";
|
|
37560
|
-
const tableBackground = "#000000";
|
|
37561
|
-
const tableBackgroundAccent = "#F9F9F9";
|
|
37562
|
-
const tableBackgroundHover = "#F5F5F5";
|
|
37563
|
-
const tableBorder = "#DDDDDD";
|
|
37564
|
-
const btnBackground = "#FFFFFF";
|
|
37565
|
-
const btnBackgroundHighlight = "rgb(230, 230, 230)";
|
|
37566
|
-
const btnBorder = "#CCCCCC";
|
|
37567
|
-
const btnPrimaryBackground = "#0088CC";
|
|
37568
|
-
const btnPrimaryBackgroundHighlight = "rgb(0, 68, 204)";
|
|
37569
|
-
const btnInfoBackground = "#5BC0DE";
|
|
37570
|
-
const btnInfoBackgroundHighlight = "#2F96B4";
|
|
37571
|
-
const btnSuccessBackground = "#62C462";
|
|
37572
|
-
const btnSuccessBackgroundHighlight = "#51A351";
|
|
37573
|
-
const btnWarningBackground = "rgb(251, 180, 81)";
|
|
37574
|
-
const btnWarningBackgroundHighlight = "#F89406";
|
|
37575
|
-
const btnDangerBackground = "#EE5F5B";
|
|
37576
|
-
const btnDangerBackgroundHighlight = "#BD362F";
|
|
37577
|
-
const btnInverseBackground = "#444444";
|
|
37578
|
-
const btnInverseBackgroundHighlight = "#222222";
|
|
37579
|
-
const inputBackground = "#FFFFFF";
|
|
37580
|
-
const inputBorder = "#CCCCCC";
|
|
37581
|
-
const inputBorderRadius = "4px";
|
|
37582
|
-
const inputDisabledBackground = "#EEEEEE";
|
|
37583
|
-
const formActionsBackground = "#F5F5F5";
|
|
37584
|
-
const inputHeight = "30px";
|
|
37585
|
-
const dropdownBackground = "#FFFFFF";
|
|
37586
|
-
const dropdownBorder = "rgba(0, 0, 0, 0.2)";
|
|
37587
|
-
const dropdownDividerTop = "#E5E5E5";
|
|
37588
|
-
const dropdownDividerBottom = "#FFFFFF";
|
|
37589
|
-
const dropdownLinkColor = "#333333";
|
|
37590
|
-
const dropdownLinkColorHover = "#FFFFFF";
|
|
37591
|
-
const dropdownLinkColorActive = "#FFFFFF";
|
|
37592
|
-
const dropdownLinkBackgroundActive = "#0088CC";
|
|
37593
|
-
const dropdownLinkBackgroundHover = "#0088CC";
|
|
37594
|
-
const zindexDropdown = 1000;
|
|
37595
|
-
const zindexPopover = 1010;
|
|
37596
|
-
const zindexTooltip = 1030;
|
|
37597
|
-
const zindexFixedNavbar = 1030;
|
|
37598
|
-
const zindexHeader = 1060;
|
|
37599
|
-
const zindexModalBackdrop = 1070;
|
|
37600
|
-
const zindexModal = 1080;
|
|
37601
|
-
const zindexAboveModal = 1090;
|
|
37602
|
-
const iconSpritePath = "../img/glyphicons-halflings.png";
|
|
37603
|
-
const iconWhiteSpritePath = "../img/glyphicons-halflings-white.png";
|
|
37604
|
-
const placeholderText = "#999999";
|
|
37605
|
-
const hrBorder = "#EEEEEE";
|
|
37606
|
-
const horizontalComponentOffset = "180px";
|
|
37607
|
-
const wellBackground = "#F5F5F5";
|
|
37608
|
-
const navbarCollapseWidth = "979px";
|
|
37609
|
-
const navbarCollapseDesktopWidth = "980px";
|
|
37610
|
-
const navbarHeight = "40px";
|
|
37611
|
-
const navbarBackgroundHighlight = "#FFFFFF";
|
|
37612
|
-
const navbarBackground = "rgb(242, 242, 242)";
|
|
37613
|
-
const navbarBorder = "rgb(212, 212, 212)";
|
|
37614
|
-
const navbarText = "#777777";
|
|
37615
|
-
const navbarLinkColor = "#777777";
|
|
37616
|
-
const navbarLinkColorHover = "#333333";
|
|
37617
|
-
const navbarLinkColorActive = "#555555";
|
|
37618
|
-
const navbarLinkBackgroundHover = "#000000";
|
|
37619
|
-
const navbarLinkBackgroundActive = "rgb(230, 230, 230)";
|
|
37620
|
-
const navbarBrandColor = "#777777";
|
|
37621
|
-
const navbarInverseBackground = "#111111";
|
|
37622
|
-
const navbarInverseBackgroundHighlight = "#222222";
|
|
37623
|
-
const navbarInverseBorder = "#252525";
|
|
37624
|
-
const navbarInverseText = "#999999";
|
|
37625
|
-
const navbarInverseLinkColor = "#999999";
|
|
37626
|
-
const navbarInverseLinkColorHover = "#FFFFFF";
|
|
37627
|
-
const navbarInverseLinkColorActive = "#FFFFFF";
|
|
37628
|
-
const navbarInverseLinkBackgroundHover = "#000000";
|
|
37629
|
-
const navbarInverseLinkBackgroundActive = "#111111";
|
|
37630
|
-
const navbarInverseSearchBackground = "rgb(82, 82, 82)";
|
|
37631
|
-
const navbarInverseSearchBackgroundFocus = "#FFFFFF";
|
|
37632
|
-
const navbarInverseSearchBorder = "#111111";
|
|
37633
|
-
const navbarInverseSearchPlaceholderColor = "#CCCCCC";
|
|
37634
|
-
const navbarInverseBrandColor = "#999999";
|
|
37635
|
-
const paginationBackground = "#FFFFFF";
|
|
37636
|
-
const paginationBorder = "#DDDDDD";
|
|
37637
|
-
const paginationActiveBackground = "#F5F5F5";
|
|
37638
|
-
const heroUnitBackground = "#EEEEEE";
|
|
37639
|
-
const heroUnitHeadingColor = "inherit";
|
|
37640
|
-
const heroUnitLeadColor = "inherit";
|
|
37641
|
-
const warningText = "#C09853";
|
|
37642
|
-
const warningBackground = "#FCF8E3";
|
|
37643
|
-
const warningBorder = "rgb(251, 239, 213)";
|
|
37644
|
-
const errorText = "#B94A48";
|
|
37645
|
-
const errorBackground = "#F2DEDE";
|
|
37646
|
-
const errorBorder = "rgb(238, 211, 215)";
|
|
37647
|
-
const successText = "#468847";
|
|
37648
|
-
const successBackground = "#DFF0D8";
|
|
37649
|
-
const successBorder = "rgb(212, 232, 197)";
|
|
37650
|
-
const infoText = "#4A7C17";
|
|
37651
|
-
const infoBackground = "#EDF2DF";
|
|
37652
|
-
const infoBorder = "rgb(228, 232, 197)";
|
|
37653
|
-
const tooltipColor = "#FFFFFF";
|
|
37654
|
-
const tooltipBackground = "#000000";
|
|
37655
|
-
const tooltipArrowWidth = "5px";
|
|
37656
|
-
const tooltipArrowColor = "#000000";
|
|
37657
|
-
const popoverBackground = "#FFFFFF";
|
|
37658
|
-
const popoverArrowWidth = "10px";
|
|
37659
|
-
const popoverArrowColor = "#FFFFFF";
|
|
37660
|
-
const popoverTitleBackground = "rgb(247, 247, 247)";
|
|
37661
|
-
const popoverArrowOuterWidth = "11px";
|
|
37662
|
-
const popoverArrowOuterColor = "rgba(0, 0, 0, 0.25)";
|
|
37663
|
-
const gridColumns = "12";
|
|
37664
|
-
const gridColumnWidth = "60px";
|
|
37665
|
-
const gridGutterWidth = "20px";
|
|
37666
|
-
const gridRowWidth = "940px";
|
|
37667
|
-
const gridColumnWidth1200 = "70px";
|
|
37668
|
-
const gridGutterWidth1200 = "30px";
|
|
37669
|
-
const gridRowWidth1200 = "1170px";
|
|
37670
|
-
const gridColumnWidth768 = "42px";
|
|
37671
|
-
const gridGutterWidth768 = "20px";
|
|
37672
|
-
const gridRowWidth768 = "724px";
|
|
37673
|
-
const fluidGridColumnWidth = "6.382978723404255%";
|
|
37674
|
-
const fluidGridGutterWidth = "2.127659574468085%";
|
|
37675
|
-
const fluidGridColumnWidth1200 = "5.982905982905983%";
|
|
37676
|
-
const fluidGridGutterWidth1200 = "2.564102564102564%";
|
|
37677
|
-
const fluidGridColumnWidth768 = "5.801104972375691%";
|
|
37678
|
-
const fluidGridGutterWidth768 = "2.7624309392265194%";
|
|
37679
|
-
const kaGreen = "#71B307";
|
|
37680
|
-
const kaGreenLight = "#BED47A";
|
|
37681
|
-
const kaBlue = "#314453";
|
|
37682
|
-
const kaBlueLight = "#4D6779";
|
|
37683
|
-
const grayExtraDark = "#111111";
|
|
37684
|
-
const grayExtraLight = "#EEEEEE";
|
|
37685
|
-
const graySuperLight = "#F7F7F7";
|
|
37686
|
-
const whiteDark = "#FDFDFD";
|
|
37687
|
-
const dark = "#21242C";
|
|
37688
|
-
const blueDarkUnsaturated = "#3B414E";
|
|
37689
|
-
const blueDarkSaturated = "#1F3043";
|
|
37690
|
-
const blueLight = "#A9C0D1";
|
|
37691
|
-
const greenLight = "#C6D1AD";
|
|
37692
|
-
const greenDark = "#356700";
|
|
37693
|
-
const yellowGreen = "#9DB63B";
|
|
37694
|
-
const okGreen = "#A7CF5B";
|
|
37695
|
-
const alertRed = "#C42420";
|
|
37696
|
-
const coral = "#EE6666";
|
|
37697
|
-
const grayBlue = "#9AB3B9";
|
|
37698
|
-
const lightPageBackground = "#FDFDFD";
|
|
37699
|
-
const yclaBlue = "#49BAD5";
|
|
37700
|
-
const yclaTeal = "#56D0B3";
|
|
37701
|
-
const yclaTealDark = "#50C1A7";
|
|
37702
|
-
const yclaGreenDark = "#3D9A82";
|
|
37703
|
-
const yclaGreen = "#81C262";
|
|
37704
|
-
const learnstormBlue = "#4898FC";
|
|
37705
|
-
const homepageBlue = "#46A8BF";
|
|
37706
|
-
const backgroundBlue = "#00294A";
|
|
37707
|
-
const teacherSignupBlue = "#335d7d";
|
|
37708
|
-
const homepageGreen = "#2B8E7B";
|
|
37709
|
-
const streakColor = "#F79734";
|
|
37710
|
-
const facebookColor = "#1A60A2";
|
|
37711
|
-
const blueGoogleColor = "#2CAFE2";
|
|
37712
|
-
const redGoogleColor = "#BF4434";
|
|
37713
|
-
const homepageColor = "#2D585E";
|
|
37714
|
-
const lightTextColor = "#898989";
|
|
37715
|
-
const fontSizeTiny = "11px";
|
|
37716
|
-
const fontSizeNormal = "14px";
|
|
37717
|
-
const fontSizeMedium = "16px";
|
|
37718
|
-
const fontSizeExtraLarge = "24px";
|
|
37719
|
-
const fontSizeHuge = "36px";
|
|
37720
|
-
const fontSizeBakana = "48px";
|
|
37721
|
-
const fontSizeBananas = "60px";
|
|
37722
|
-
const fixedWidthFontFamily = "'Helvetica Neue',Helvetica,Arial,sans-serif";
|
|
37723
|
-
const contentPadding = "20px";
|
|
37724
|
-
const primaryButtonBackground = "#89B908";
|
|
37725
|
-
const primaryButtonBorder = "#76A005";
|
|
37726
|
-
const buttonTextColor = "rgb(122, 122, 122)";
|
|
37727
|
-
const buttonBorderRadius = "3px";
|
|
37728
|
-
const basicBorderColor = "#CCCCCC";
|
|
37729
|
-
const minContainerWidth = "1000px";
|
|
37730
|
-
const maxContainerWidth = "1200px";
|
|
37731
|
-
const formHintColor = "#999999";
|
|
37732
|
-
const guidelineExampleText = "#606060";
|
|
37733
|
-
const hoverCardWidth = "450px";
|
|
37734
|
-
const menuHighlightColor = "#96AB4F";
|
|
37735
|
-
const menuHighlightBorderColor = "#76A005";
|
|
37736
|
-
const menuActiveTextColor = "#FFFFFF";
|
|
37737
|
-
const menuInactiveTextColor = "#444444";
|
|
37738
|
-
const menuSubheaderTextColor = "rgb(120, 120, 120)";
|
|
37739
|
-
const menuBorderColor = "#94A170";
|
|
37740
|
-
const unreadBackgroundColor = "#ECEEF4";
|
|
37741
|
-
const menuLineHeight = "18px";
|
|
37742
|
-
const menuSubheaderLineHeight = "17px";
|
|
37743
|
-
const menuSubheaderFontSize = "9px";
|
|
37744
|
-
const notificationBarColor = "#4858A4";
|
|
37745
|
-
const modalBodyTopPadding = "20px";
|
|
37746
|
-
const modalDialogPadding = "15px";
|
|
37747
|
-
const modalSectionPadding = "9px";
|
|
37748
|
-
const mathDomain1 = "#11ACCD";
|
|
37749
|
-
const mathDomain2 = "#63D9EA";
|
|
37750
|
-
const mathDomain3 = "#027d97";
|
|
37751
|
-
const mathDomain4 = "#085566";
|
|
37752
|
-
const partnerContentDomain1 = "#01A995";
|
|
37753
|
-
const partnerContentDomain2 = "#01D1C1";
|
|
37754
|
-
const partnerContentDomain3 = "#208170";
|
|
37755
|
-
const partnerContentDomain4 = "#144F44";
|
|
37756
|
-
const csDomain1 = "#1FAB54";
|
|
37757
|
-
const csDomain2 = "#74CF70";
|
|
37758
|
-
const csDomain3 = "#0D923F";
|
|
37759
|
-
const csDomain4 = "#085E29";
|
|
37760
|
-
const economicsDomain1 = "#E07D10";
|
|
37761
|
-
const economicsDomain2 = "#FFBE26";
|
|
37762
|
-
const economicsDomain3 = "#A75A05";
|
|
37763
|
-
const economicsDomain4 = "#953C02";
|
|
37764
|
-
const collegeCareersMoreDomain1 = "#01A995";
|
|
37765
|
-
const collegeCareersMoreDomain2 = "#01D1C1";
|
|
37766
|
-
const collegeCareersMoreDomain3 = "#208170";
|
|
37767
|
-
const collegeCareersMoreDomain4 = "#144F44";
|
|
37768
|
-
const humanitiesDomain1 = "#E84D39";
|
|
37769
|
-
const humanitiesDomain2 = "#FF8482";
|
|
37770
|
-
const humanitiesDomain3 = "#BE2612";
|
|
37771
|
-
const humanitiesDomain4 = "#8C1C0D";
|
|
37772
|
-
const gtpDomain1 = "#1865F2";
|
|
37773
|
-
const gtpDomain2 = "#1865F2";
|
|
37774
|
-
const gtpDomain3 = "#1865F2";
|
|
37775
|
-
const gtpDomain4 = "#1865F2";
|
|
37776
|
-
const scienceDomain1 = "#CA337C";
|
|
37777
|
-
const scienceDomain2 = "#FF92C6";
|
|
37778
|
-
const scienceDomain3 = "#9E034E";
|
|
37779
|
-
const scienceDomain4 = "#6B0235";
|
|
37780
|
-
const testPrepDomain1 = "#1865F2";
|
|
37781
|
-
const testPrepDomain2 = "#1865F2";
|
|
37782
|
-
const testPrepDomain3 = "#1865F2";
|
|
37783
|
-
const testPrepDomain4 = "#1865F2";
|
|
37784
|
-
const defaultDomain1 = "#1865F2";
|
|
37785
|
-
const defaultDomain2 = "#66afe9";
|
|
37786
|
-
const defaultDomain3 = "#1152b0";
|
|
37787
|
-
const defaultDomain4 = "#0d3d82";
|
|
37788
|
-
const defaultDomainColor = "#314453";
|
|
37789
|
-
const defaultSubjectColor = "#4D6779";
|
|
37790
|
-
const defaultTopicColor = "#6A8DA6";
|
|
37791
|
-
const defaultHoverColor = "#314453";
|
|
37792
|
-
const defaultLinkColor = "#314453";
|
|
37793
|
-
const defaultLinkHoverColor = "#6A8DA6";
|
|
37794
|
-
const scienceDomainColor = "#94424F";
|
|
37795
|
-
const scienceSubjectColor = "#9D4A5A";
|
|
37796
|
-
const scienceTopicColor = "#C55F73";
|
|
37797
|
-
const scienceHoverColor = "#94424F";
|
|
37798
|
-
const scienceLinkColor = "#94424F";
|
|
37799
|
-
const scienceLinkHoverColor = "#C55F73";
|
|
37800
|
-
const humanitiesDomainColor = "#AD3434";
|
|
37801
|
-
const humanitiesSubjectColor = "#C13B31";
|
|
37802
|
-
const humanitiesTopicColor = "#D24A45";
|
|
37803
|
-
const humanitiesHoverColor = "#AD3434";
|
|
37804
|
-
const humanitiesLinkColor = "#AD3434";
|
|
37805
|
-
const humanitiesLinkHoverColor = "#D24A45";
|
|
37806
|
-
const economicsDomainColor = "#B77033";
|
|
37807
|
-
const economicsSubjectColor = "#BF7B34";
|
|
37808
|
-
const economicsTopicColor = "#D1933B";
|
|
37809
|
-
const economicsHoverColor = "#B77033";
|
|
37810
|
-
const economicsLinkColor = "#B77033";
|
|
37811
|
-
const economicsLinkHoverColor = "#D1933B";
|
|
37812
|
-
const csDomainColor = "#437A39";
|
|
37813
|
-
const csSubjectColor = "#53893E";
|
|
37814
|
-
const csTopicColor = "#689B51";
|
|
37815
|
-
const csHoverColor = "#437A39";
|
|
37816
|
-
const csLinkColor = "#437A39";
|
|
37817
|
-
const csLinkHoverColor = "#689B51";
|
|
37818
|
-
const partnerContentDomainColor = "#218270";
|
|
37819
|
-
const partnerContentSubjectColor = "#2C8D7B";
|
|
37820
|
-
const partnerContentTopicColor = "#329A86";
|
|
37821
|
-
const partnerContentHoverColor = "#218270";
|
|
37822
|
-
const partnerContentLinkColor = "#218270";
|
|
37823
|
-
const partnerContentLinkHoverColor = "#329A86";
|
|
37824
|
-
const essayDomainColor = "#0071B3";
|
|
37825
|
-
const mathDomainColor = "#1C758A";
|
|
37826
|
-
const mathSubjectColor = "#46A8BF";
|
|
37827
|
-
const mathTopicColor = "#4FBAD4";
|
|
37828
|
-
const mathHoverColor = "#1C758A";
|
|
37829
|
-
const mathLinkColor = "#1C758A";
|
|
37830
|
-
const mathLinkHoverColor = "#4FBAD4";
|
|
37831
|
-
const testPrepDomainColor = "#644172";
|
|
37832
|
-
const testPrepSubjectColor = "#7E5F8E";
|
|
37833
|
-
const testPrepTopicColor = "#9A72AC";
|
|
37834
|
-
const testPrepHoverColor = "#644172";
|
|
37835
|
-
const testPrepLinkColor = "#644172";
|
|
37836
|
-
const testPrepLinkHoverColor = "#9A72AC";
|
|
37837
|
-
const collegeCareersMoreDomainColor = "#218270";
|
|
37838
|
-
const collegeCareersMoreSubjectColor = "#2C8D7B";
|
|
37839
|
-
const collegeCareersMoreTopicColor = "#329A86";
|
|
37840
|
-
const collegeCareersMoreHoverColor = "#218270";
|
|
37841
|
-
const collegeCareersMoreLinkColor = "#218270";
|
|
37842
|
-
const collegeCareersMoreLinkHoverColor = "#329A86";
|
|
37843
|
-
const colorProficient = "#1C758A";
|
|
37844
|
-
const colorPracticed = "rgb(158, 221, 235)";
|
|
37845
|
-
const colorMastery1 = "rgb(90, 197, 221)";
|
|
37846
|
-
const colorMastery2 = "rgb(42, 174, 203)";
|
|
37847
|
-
const colorMastery3 = "#1C758A";
|
|
37848
|
-
const colorSuggested = "#73982C";
|
|
37849
|
-
const colorReview = "#E35D04";
|
|
37850
|
-
const colorNotStarted = "#CCCCCC";
|
|
37851
|
-
const colorStarted = "#C7E5F7";
|
|
37852
|
-
const colorStruggling = "#C30202";
|
|
37853
|
-
const colorPersonal = "#00809C";
|
|
37854
|
-
const colorPractice = "#96D9FF";
|
|
37855
|
-
const colorEnergyPoints = "#005987";
|
|
37856
|
-
const pureSmMin = "568px";
|
|
37857
|
-
const pureMdMin = "768px";
|
|
37858
|
-
const pureLgMin = "1024px";
|
|
37859
|
-
const pureXlMin = "1200px";
|
|
37860
|
-
const pureXsMax = "567px";
|
|
37861
|
-
const pureSmMax = "767px";
|
|
37862
|
-
const pureMdMax = "1023px";
|
|
37863
|
-
const pureLgMax = "1199px";
|
|
37864
|
-
|
|
37865
|
-
var globalConstants = /*#__PURE__*/Object.freeze({
|
|
37866
|
-
__proto__: null,
|
|
37867
|
-
black: black,
|
|
37868
|
-
grayDarker: grayDarker,
|
|
37869
|
-
grayDark: grayDark,
|
|
37870
|
-
gray: gray,
|
|
37871
|
-
grayLight: grayLight,
|
|
37872
|
-
grayLighter: grayLighter,
|
|
37873
|
-
white: white,
|
|
37874
|
-
blue: blue,
|
|
37875
|
-
blueDark: blueDark,
|
|
37876
|
-
green: green,
|
|
37877
|
-
red: red,
|
|
37878
|
-
yellow: yellow,
|
|
37879
|
-
orange: orange,
|
|
37880
|
-
pink: pink,
|
|
37881
|
-
purple: purple,
|
|
37882
|
-
bodyBackground: bodyBackground,
|
|
37883
|
-
textColor: textColor,
|
|
37884
|
-
linkColor: linkColor,
|
|
37885
|
-
linkColorHover: linkColorHover,
|
|
37886
|
-
sansFontFamily: sansFontFamily,
|
|
37887
|
-
serifFontFamily: serifFontFamily,
|
|
37888
|
-
monoFontFamily: monoFontFamily,
|
|
37889
|
-
baseFontSize: baseFontSize,
|
|
37890
|
-
baseFontFamily: baseFontFamily,
|
|
37891
|
-
baseLineHeight: baseLineHeight,
|
|
37892
|
-
altFontFamily: altFontFamily,
|
|
37893
|
-
headingsFontFamily: headingsFontFamily,
|
|
37894
|
-
headingsFontWeight: headingsFontWeight,
|
|
37895
|
-
headingsColor: headingsColor,
|
|
37896
|
-
fontSizeLarge: fontSizeLarge,
|
|
37897
|
-
fontSizeSmall: fontSizeSmall,
|
|
37898
|
-
fontSizeMini: fontSizeMini,
|
|
37899
|
-
paddingLarge: paddingLarge,
|
|
37900
|
-
paddingSmall: paddingSmall,
|
|
37901
|
-
paddingMini: paddingMini,
|
|
37902
|
-
baseBorderRadius: baseBorderRadius,
|
|
37903
|
-
borderRadiusLarge: borderRadiusLarge,
|
|
37904
|
-
borderRadiusSmall: borderRadiusSmall,
|
|
37905
|
-
tableBackground: tableBackground,
|
|
37906
|
-
tableBackgroundAccent: tableBackgroundAccent,
|
|
37907
|
-
tableBackgroundHover: tableBackgroundHover,
|
|
37908
|
-
tableBorder: tableBorder,
|
|
37909
|
-
btnBackground: btnBackground,
|
|
37910
|
-
btnBackgroundHighlight: btnBackgroundHighlight,
|
|
37911
|
-
btnBorder: btnBorder,
|
|
37912
|
-
btnPrimaryBackground: btnPrimaryBackground,
|
|
37913
|
-
btnPrimaryBackgroundHighlight: btnPrimaryBackgroundHighlight,
|
|
37914
|
-
btnInfoBackground: btnInfoBackground,
|
|
37915
|
-
btnInfoBackgroundHighlight: btnInfoBackgroundHighlight,
|
|
37916
|
-
btnSuccessBackground: btnSuccessBackground,
|
|
37917
|
-
btnSuccessBackgroundHighlight: btnSuccessBackgroundHighlight,
|
|
37918
|
-
btnWarningBackground: btnWarningBackground,
|
|
37919
|
-
btnWarningBackgroundHighlight: btnWarningBackgroundHighlight,
|
|
37920
|
-
btnDangerBackground: btnDangerBackground,
|
|
37921
|
-
btnDangerBackgroundHighlight: btnDangerBackgroundHighlight,
|
|
37922
|
-
btnInverseBackground: btnInverseBackground,
|
|
37923
|
-
btnInverseBackgroundHighlight: btnInverseBackgroundHighlight,
|
|
37924
|
-
inputBackground: inputBackground,
|
|
37925
|
-
inputBorder: inputBorder,
|
|
37926
|
-
inputBorderRadius: inputBorderRadius,
|
|
37927
|
-
inputDisabledBackground: inputDisabledBackground,
|
|
37928
|
-
formActionsBackground: formActionsBackground,
|
|
37929
|
-
inputHeight: inputHeight,
|
|
37930
|
-
dropdownBackground: dropdownBackground,
|
|
37931
|
-
dropdownBorder: dropdownBorder,
|
|
37932
|
-
dropdownDividerTop: dropdownDividerTop,
|
|
37933
|
-
dropdownDividerBottom: dropdownDividerBottom,
|
|
37934
|
-
dropdownLinkColor: dropdownLinkColor,
|
|
37935
|
-
dropdownLinkColorHover: dropdownLinkColorHover,
|
|
37936
|
-
dropdownLinkColorActive: dropdownLinkColorActive,
|
|
37937
|
-
dropdownLinkBackgroundActive: dropdownLinkBackgroundActive,
|
|
37938
|
-
dropdownLinkBackgroundHover: dropdownLinkBackgroundHover,
|
|
37939
|
-
zindexDropdown: zindexDropdown,
|
|
37940
|
-
zindexPopover: zindexPopover,
|
|
37941
|
-
zindexTooltip: zindexTooltip,
|
|
37942
|
-
zindexFixedNavbar: zindexFixedNavbar,
|
|
37943
|
-
zindexHeader: zindexHeader,
|
|
37944
|
-
zindexModalBackdrop: zindexModalBackdrop,
|
|
37945
|
-
zindexModal: zindexModal,
|
|
37946
|
-
zindexAboveModal: zindexAboveModal,
|
|
37947
|
-
iconSpritePath: iconSpritePath,
|
|
37948
|
-
iconWhiteSpritePath: iconWhiteSpritePath,
|
|
37949
|
-
placeholderText: placeholderText,
|
|
37950
|
-
hrBorder: hrBorder,
|
|
37951
|
-
horizontalComponentOffset: horizontalComponentOffset,
|
|
37952
|
-
wellBackground: wellBackground,
|
|
37953
|
-
navbarCollapseWidth: navbarCollapseWidth,
|
|
37954
|
-
navbarCollapseDesktopWidth: navbarCollapseDesktopWidth,
|
|
37955
|
-
navbarHeight: navbarHeight,
|
|
37956
|
-
navbarBackgroundHighlight: navbarBackgroundHighlight,
|
|
37957
|
-
navbarBackground: navbarBackground,
|
|
37958
|
-
navbarBorder: navbarBorder,
|
|
37959
|
-
navbarText: navbarText,
|
|
37960
|
-
navbarLinkColor: navbarLinkColor,
|
|
37961
|
-
navbarLinkColorHover: navbarLinkColorHover,
|
|
37962
|
-
navbarLinkColorActive: navbarLinkColorActive,
|
|
37963
|
-
navbarLinkBackgroundHover: navbarLinkBackgroundHover,
|
|
37964
|
-
navbarLinkBackgroundActive: navbarLinkBackgroundActive,
|
|
37965
|
-
navbarBrandColor: navbarBrandColor,
|
|
37966
|
-
navbarInverseBackground: navbarInverseBackground,
|
|
37967
|
-
navbarInverseBackgroundHighlight: navbarInverseBackgroundHighlight,
|
|
37968
|
-
navbarInverseBorder: navbarInverseBorder,
|
|
37969
|
-
navbarInverseText: navbarInverseText,
|
|
37970
|
-
navbarInverseLinkColor: navbarInverseLinkColor,
|
|
37971
|
-
navbarInverseLinkColorHover: navbarInverseLinkColorHover,
|
|
37972
|
-
navbarInverseLinkColorActive: navbarInverseLinkColorActive,
|
|
37973
|
-
navbarInverseLinkBackgroundHover: navbarInverseLinkBackgroundHover,
|
|
37974
|
-
navbarInverseLinkBackgroundActive: navbarInverseLinkBackgroundActive,
|
|
37975
|
-
navbarInverseSearchBackground: navbarInverseSearchBackground,
|
|
37976
|
-
navbarInverseSearchBackgroundFocus: navbarInverseSearchBackgroundFocus,
|
|
37977
|
-
navbarInverseSearchBorder: navbarInverseSearchBorder,
|
|
37978
|
-
navbarInverseSearchPlaceholderColor: navbarInverseSearchPlaceholderColor,
|
|
37979
|
-
navbarInverseBrandColor: navbarInverseBrandColor,
|
|
37980
|
-
paginationBackground: paginationBackground,
|
|
37981
|
-
paginationBorder: paginationBorder,
|
|
37982
|
-
paginationActiveBackground: paginationActiveBackground,
|
|
37983
|
-
heroUnitBackground: heroUnitBackground,
|
|
37984
|
-
heroUnitHeadingColor: heroUnitHeadingColor,
|
|
37985
|
-
heroUnitLeadColor: heroUnitLeadColor,
|
|
37986
|
-
warningText: warningText,
|
|
37987
|
-
warningBackground: warningBackground,
|
|
37988
|
-
warningBorder: warningBorder,
|
|
37989
|
-
errorText: errorText,
|
|
37990
|
-
errorBackground: errorBackground,
|
|
37991
|
-
errorBorder: errorBorder,
|
|
37992
|
-
successText: successText,
|
|
37993
|
-
successBackground: successBackground,
|
|
37994
|
-
successBorder: successBorder,
|
|
37995
|
-
infoText: infoText,
|
|
37996
|
-
infoBackground: infoBackground,
|
|
37997
|
-
infoBorder: infoBorder,
|
|
37998
|
-
tooltipColor: tooltipColor,
|
|
37999
|
-
tooltipBackground: tooltipBackground,
|
|
38000
|
-
tooltipArrowWidth: tooltipArrowWidth,
|
|
38001
|
-
tooltipArrowColor: tooltipArrowColor,
|
|
38002
|
-
popoverBackground: popoverBackground,
|
|
38003
|
-
popoverArrowWidth: popoverArrowWidth,
|
|
38004
|
-
popoverArrowColor: popoverArrowColor,
|
|
38005
|
-
popoverTitleBackground: popoverTitleBackground,
|
|
38006
|
-
popoverArrowOuterWidth: popoverArrowOuterWidth,
|
|
38007
|
-
popoverArrowOuterColor: popoverArrowOuterColor,
|
|
38008
|
-
gridColumns: gridColumns,
|
|
38009
|
-
gridColumnWidth: gridColumnWidth,
|
|
38010
|
-
gridGutterWidth: gridGutterWidth,
|
|
38011
|
-
gridRowWidth: gridRowWidth,
|
|
38012
|
-
gridColumnWidth1200: gridColumnWidth1200,
|
|
38013
|
-
gridGutterWidth1200: gridGutterWidth1200,
|
|
38014
|
-
gridRowWidth1200: gridRowWidth1200,
|
|
38015
|
-
gridColumnWidth768: gridColumnWidth768,
|
|
38016
|
-
gridGutterWidth768: gridGutterWidth768,
|
|
38017
|
-
gridRowWidth768: gridRowWidth768,
|
|
38018
|
-
fluidGridColumnWidth: fluidGridColumnWidth,
|
|
38019
|
-
fluidGridGutterWidth: fluidGridGutterWidth,
|
|
38020
|
-
fluidGridColumnWidth1200: fluidGridColumnWidth1200,
|
|
38021
|
-
fluidGridGutterWidth1200: fluidGridGutterWidth1200,
|
|
38022
|
-
fluidGridColumnWidth768: fluidGridColumnWidth768,
|
|
38023
|
-
fluidGridGutterWidth768: fluidGridGutterWidth768,
|
|
38024
|
-
kaGreen: kaGreen,
|
|
38025
|
-
kaGreenLight: kaGreenLight,
|
|
38026
|
-
kaBlue: kaBlue,
|
|
38027
|
-
kaBlueLight: kaBlueLight,
|
|
38028
|
-
grayExtraDark: grayExtraDark,
|
|
38029
|
-
grayExtraLight: grayExtraLight,
|
|
38030
|
-
graySuperLight: graySuperLight,
|
|
38031
|
-
whiteDark: whiteDark,
|
|
38032
|
-
dark: dark,
|
|
38033
|
-
blueDarkUnsaturated: blueDarkUnsaturated,
|
|
38034
|
-
blueDarkSaturated: blueDarkSaturated,
|
|
38035
|
-
blueLight: blueLight,
|
|
38036
|
-
greenLight: greenLight,
|
|
38037
|
-
greenDark: greenDark,
|
|
38038
|
-
yellowGreen: yellowGreen,
|
|
38039
|
-
okGreen: okGreen,
|
|
38040
|
-
alertRed: alertRed,
|
|
38041
|
-
coral: coral,
|
|
38042
|
-
grayBlue: grayBlue,
|
|
38043
|
-
lightPageBackground: lightPageBackground,
|
|
38044
|
-
yclaBlue: yclaBlue,
|
|
38045
|
-
yclaTeal: yclaTeal,
|
|
38046
|
-
yclaTealDark: yclaTealDark,
|
|
38047
|
-
yclaGreenDark: yclaGreenDark,
|
|
38048
|
-
yclaGreen: yclaGreen,
|
|
38049
|
-
learnstormBlue: learnstormBlue,
|
|
38050
|
-
homepageBlue: homepageBlue,
|
|
38051
|
-
backgroundBlue: backgroundBlue,
|
|
38052
|
-
teacherSignupBlue: teacherSignupBlue,
|
|
38053
|
-
homepageGreen: homepageGreen,
|
|
38054
|
-
streakColor: streakColor,
|
|
38055
|
-
facebookColor: facebookColor,
|
|
38056
|
-
blueGoogleColor: blueGoogleColor,
|
|
38057
|
-
redGoogleColor: redGoogleColor,
|
|
38058
|
-
homepageColor: homepageColor,
|
|
38059
|
-
lightTextColor: lightTextColor,
|
|
38060
|
-
fontSizeTiny: fontSizeTiny,
|
|
38061
|
-
fontSizeNormal: fontSizeNormal,
|
|
38062
|
-
fontSizeMedium: fontSizeMedium,
|
|
38063
|
-
fontSizeExtraLarge: fontSizeExtraLarge,
|
|
38064
|
-
fontSizeHuge: fontSizeHuge,
|
|
38065
|
-
fontSizeBakana: fontSizeBakana,
|
|
38066
|
-
fontSizeBananas: fontSizeBananas,
|
|
38067
|
-
fixedWidthFontFamily: fixedWidthFontFamily,
|
|
38068
|
-
contentPadding: contentPadding,
|
|
38069
|
-
primaryButtonBackground: primaryButtonBackground,
|
|
38070
|
-
primaryButtonBorder: primaryButtonBorder,
|
|
38071
|
-
buttonTextColor: buttonTextColor,
|
|
38072
|
-
buttonBorderRadius: buttonBorderRadius,
|
|
38073
|
-
basicBorderColor: basicBorderColor,
|
|
38074
|
-
minContainerWidth: minContainerWidth,
|
|
38075
|
-
maxContainerWidth: maxContainerWidth,
|
|
38076
|
-
formHintColor: formHintColor,
|
|
38077
|
-
guidelineExampleText: guidelineExampleText,
|
|
38078
|
-
hoverCardWidth: hoverCardWidth,
|
|
38079
|
-
menuHighlightColor: menuHighlightColor,
|
|
38080
|
-
menuHighlightBorderColor: menuHighlightBorderColor,
|
|
38081
|
-
menuActiveTextColor: menuActiveTextColor,
|
|
38082
|
-
menuInactiveTextColor: menuInactiveTextColor,
|
|
38083
|
-
menuSubheaderTextColor: menuSubheaderTextColor,
|
|
38084
|
-
menuBorderColor: menuBorderColor,
|
|
38085
|
-
unreadBackgroundColor: unreadBackgroundColor,
|
|
38086
|
-
menuLineHeight: menuLineHeight,
|
|
38087
|
-
menuSubheaderLineHeight: menuSubheaderLineHeight,
|
|
38088
|
-
menuSubheaderFontSize: menuSubheaderFontSize,
|
|
38089
|
-
notificationBarColor: notificationBarColor,
|
|
38090
|
-
modalBodyTopPadding: modalBodyTopPadding,
|
|
38091
|
-
modalDialogPadding: modalDialogPadding,
|
|
38092
|
-
modalSectionPadding: modalSectionPadding,
|
|
38093
|
-
mathDomain1: mathDomain1,
|
|
38094
|
-
mathDomain2: mathDomain2,
|
|
38095
|
-
mathDomain3: mathDomain3,
|
|
38096
|
-
mathDomain4: mathDomain4,
|
|
38097
|
-
partnerContentDomain1: partnerContentDomain1,
|
|
38098
|
-
partnerContentDomain2: partnerContentDomain2,
|
|
38099
|
-
partnerContentDomain3: partnerContentDomain3,
|
|
38100
|
-
partnerContentDomain4: partnerContentDomain4,
|
|
38101
|
-
csDomain1: csDomain1,
|
|
38102
|
-
csDomain2: csDomain2,
|
|
38103
|
-
csDomain3: csDomain3,
|
|
38104
|
-
csDomain4: csDomain4,
|
|
38105
|
-
economicsDomain1: economicsDomain1,
|
|
38106
|
-
economicsDomain2: economicsDomain2,
|
|
38107
|
-
economicsDomain3: economicsDomain3,
|
|
38108
|
-
economicsDomain4: economicsDomain4,
|
|
38109
|
-
collegeCareersMoreDomain1: collegeCareersMoreDomain1,
|
|
38110
|
-
collegeCareersMoreDomain2: collegeCareersMoreDomain2,
|
|
38111
|
-
collegeCareersMoreDomain3: collegeCareersMoreDomain3,
|
|
38112
|
-
collegeCareersMoreDomain4: collegeCareersMoreDomain4,
|
|
38113
|
-
humanitiesDomain1: humanitiesDomain1,
|
|
38114
|
-
humanitiesDomain2: humanitiesDomain2,
|
|
38115
|
-
humanitiesDomain3: humanitiesDomain3,
|
|
38116
|
-
humanitiesDomain4: humanitiesDomain4,
|
|
38117
|
-
gtpDomain1: gtpDomain1,
|
|
38118
|
-
gtpDomain2: gtpDomain2,
|
|
38119
|
-
gtpDomain3: gtpDomain3,
|
|
38120
|
-
gtpDomain4: gtpDomain4,
|
|
38121
|
-
scienceDomain1: scienceDomain1,
|
|
38122
|
-
scienceDomain2: scienceDomain2,
|
|
38123
|
-
scienceDomain3: scienceDomain3,
|
|
38124
|
-
scienceDomain4: scienceDomain4,
|
|
38125
|
-
testPrepDomain1: testPrepDomain1,
|
|
38126
|
-
testPrepDomain2: testPrepDomain2,
|
|
38127
|
-
testPrepDomain3: testPrepDomain3,
|
|
38128
|
-
testPrepDomain4: testPrepDomain4,
|
|
38129
|
-
defaultDomain1: defaultDomain1,
|
|
38130
|
-
defaultDomain2: defaultDomain2,
|
|
38131
|
-
defaultDomain3: defaultDomain3,
|
|
38132
|
-
defaultDomain4: defaultDomain4,
|
|
38133
|
-
defaultDomainColor: defaultDomainColor,
|
|
38134
|
-
defaultSubjectColor: defaultSubjectColor,
|
|
38135
|
-
defaultTopicColor: defaultTopicColor,
|
|
38136
|
-
defaultHoverColor: defaultHoverColor,
|
|
38137
|
-
defaultLinkColor: defaultLinkColor,
|
|
38138
|
-
defaultLinkHoverColor: defaultLinkHoverColor,
|
|
38139
|
-
scienceDomainColor: scienceDomainColor,
|
|
38140
|
-
scienceSubjectColor: scienceSubjectColor,
|
|
38141
|
-
scienceTopicColor: scienceTopicColor,
|
|
38142
|
-
scienceHoverColor: scienceHoverColor,
|
|
38143
|
-
scienceLinkColor: scienceLinkColor,
|
|
38144
|
-
scienceLinkHoverColor: scienceLinkHoverColor,
|
|
38145
|
-
humanitiesDomainColor: humanitiesDomainColor,
|
|
38146
|
-
humanitiesSubjectColor: humanitiesSubjectColor,
|
|
38147
|
-
humanitiesTopicColor: humanitiesTopicColor,
|
|
38148
|
-
humanitiesHoverColor: humanitiesHoverColor,
|
|
38149
|
-
humanitiesLinkColor: humanitiesLinkColor,
|
|
38150
|
-
humanitiesLinkHoverColor: humanitiesLinkHoverColor,
|
|
38151
|
-
economicsDomainColor: economicsDomainColor,
|
|
38152
|
-
economicsSubjectColor: economicsSubjectColor,
|
|
38153
|
-
economicsTopicColor: economicsTopicColor,
|
|
38154
|
-
economicsHoverColor: economicsHoverColor,
|
|
38155
|
-
economicsLinkColor: economicsLinkColor,
|
|
38156
|
-
economicsLinkHoverColor: economicsLinkHoverColor,
|
|
38157
|
-
csDomainColor: csDomainColor,
|
|
38158
|
-
csSubjectColor: csSubjectColor,
|
|
38159
|
-
csTopicColor: csTopicColor,
|
|
38160
|
-
csHoverColor: csHoverColor,
|
|
38161
|
-
csLinkColor: csLinkColor,
|
|
38162
|
-
csLinkHoverColor: csLinkHoverColor,
|
|
38163
|
-
partnerContentDomainColor: partnerContentDomainColor,
|
|
38164
|
-
partnerContentSubjectColor: partnerContentSubjectColor,
|
|
38165
|
-
partnerContentTopicColor: partnerContentTopicColor,
|
|
38166
|
-
partnerContentHoverColor: partnerContentHoverColor,
|
|
38167
|
-
partnerContentLinkColor: partnerContentLinkColor,
|
|
38168
|
-
partnerContentLinkHoverColor: partnerContentLinkHoverColor,
|
|
38169
|
-
essayDomainColor: essayDomainColor,
|
|
38170
|
-
mathDomainColor: mathDomainColor,
|
|
38171
|
-
mathSubjectColor: mathSubjectColor,
|
|
38172
|
-
mathTopicColor: mathTopicColor,
|
|
38173
|
-
mathHoverColor: mathHoverColor,
|
|
38174
|
-
mathLinkColor: mathLinkColor,
|
|
38175
|
-
mathLinkHoverColor: mathLinkHoverColor,
|
|
38176
|
-
testPrepDomainColor: testPrepDomainColor,
|
|
38177
|
-
testPrepSubjectColor: testPrepSubjectColor,
|
|
38178
|
-
testPrepTopicColor: testPrepTopicColor,
|
|
38179
|
-
testPrepHoverColor: testPrepHoverColor,
|
|
38180
|
-
testPrepLinkColor: testPrepLinkColor,
|
|
38181
|
-
testPrepLinkHoverColor: testPrepLinkHoverColor,
|
|
38182
|
-
collegeCareersMoreDomainColor: collegeCareersMoreDomainColor,
|
|
38183
|
-
collegeCareersMoreSubjectColor: collegeCareersMoreSubjectColor,
|
|
38184
|
-
collegeCareersMoreTopicColor: collegeCareersMoreTopicColor,
|
|
38185
|
-
collegeCareersMoreHoverColor: collegeCareersMoreHoverColor,
|
|
38186
|
-
collegeCareersMoreLinkColor: collegeCareersMoreLinkColor,
|
|
38187
|
-
collegeCareersMoreLinkHoverColor: collegeCareersMoreLinkHoverColor,
|
|
38188
|
-
colorProficient: colorProficient,
|
|
38189
|
-
colorPracticed: colorPracticed,
|
|
38190
|
-
colorMastery1: colorMastery1,
|
|
38191
|
-
colorMastery2: colorMastery2,
|
|
38192
|
-
colorMastery3: colorMastery3,
|
|
38193
|
-
colorSuggested: colorSuggested,
|
|
38194
|
-
colorReview: colorReview,
|
|
38195
|
-
colorNotStarted: colorNotStarted,
|
|
38196
|
-
colorStarted: colorStarted,
|
|
38197
|
-
colorStruggling: colorStruggling,
|
|
38198
|
-
colorPersonal: colorPersonal,
|
|
38199
|
-
colorPractice: colorPractice,
|
|
38200
|
-
colorEnergyPoints: colorEnergyPoints,
|
|
38201
|
-
pureSmMin: pureSmMin,
|
|
38202
|
-
pureMdMin: pureMdMin,
|
|
38203
|
-
pureLgMin: pureLgMin,
|
|
38204
|
-
pureXlMin: pureXlMin,
|
|
38205
|
-
pureXsMax: pureXsMax,
|
|
38206
|
-
pureSmMax: pureSmMax,
|
|
38207
|
-
pureMdMax: pureMdMax,
|
|
38208
|
-
pureLgMax: pureLgMax
|
|
38209
|
-
});
|
|
38210
|
-
|
|
38211
|
-
const colors = {
|
|
38212
|
-
white: "#FFFFFF",
|
|
38213
|
-
gray98: "#FAFAFA",
|
|
38214
|
-
gray97: "#F6F7F7",
|
|
38215
|
-
gray95: "#F0F1F2",
|
|
38216
|
-
gray90: "#E3E5E6",
|
|
38217
|
-
gray85: "#D6D8DA",
|
|
38218
|
-
gray76: "#BABEC2",
|
|
38219
|
-
gray72: "#999A9D",
|
|
38220
|
-
gray68: "#888D93",
|
|
38221
|
-
gray55: "#707378",
|
|
38222
|
-
gray41: "#626569",
|
|
38223
|
-
gray25: "#3B3E40",
|
|
38224
|
-
gray17: "#21242C",
|
|
38225
|
-
gray10: "#1499af",
|
|
38226
|
-
black: "#000000",
|
|
38227
|
-
// These colors are pulled out from constants.js, which is itself generated
|
|
38228
|
-
// from variables.less. We should probably avoid duplicating these here.
|
|
38229
|
-
alertRed,
|
|
38230
|
-
homepageBlue,
|
|
38231
|
-
kaBlue,
|
|
38232
|
-
kaBlueLight,
|
|
38233
|
-
kaGreen,
|
|
38234
|
-
kaGreenLight,
|
|
38235
|
-
learnstormBlue,
|
|
38236
|
-
backgroundBlue,
|
|
38237
|
-
adminGreen: "#78C008",
|
|
38238
|
-
kaBlueExtraLight: "#39c2db",
|
|
38239
|
-
kaBlueHover: "#0c7f99",
|
|
38240
|
-
kaGreenHover: "#518005",
|
|
38241
|
-
// Domain-agnostic colors related to the study guide experience in the
|
|
38242
|
-
// content library.
|
|
38243
|
-
skyDark: "#001f4d",
|
|
38244
|
-
recommendationGold: "#ffbe26",
|
|
38245
|
-
starAced: "#ff9c39",
|
|
38246
|
-
// We interploate the domain colors into this colors object for
|
|
38247
|
-
// historical reasons, but everyone using domain-specific colors
|
|
38248
|
-
// should switch to using the domainColors() function to look up
|
|
38249
|
-
// colors instead.
|
|
38250
|
-
//
|
|
38251
|
-
// TODO(davidflanagan): remove this line once everything is
|
|
38252
|
-
// working correctly with the domainColors() accessor.
|
|
38253
|
-
// ...domainToColorsMap,
|
|
38254
|
-
// mission: missionColors,
|
|
38255
|
-
|
|
38256
|
-
// Colors for various OAuth providers
|
|
38257
|
-
google: "#C1432f",
|
|
38258
|
-
modernGoogle: "#be2612",
|
|
38259
|
-
modernGoogleHover: "#8c1c0d",
|
|
38260
|
-
facebook: "#4267B2",
|
|
38261
|
-
modernFacebook: "#4267B2",
|
|
38262
|
-
modernFacebookHover: "#00294a",
|
|
38263
|
-
wonderBlocksGold: "#FFB100",
|
|
38264
|
-
wonderBlocksLightBlue: "#37C5FD",
|
|
38265
|
-
// We're using rgba instead of opacity to avoid affecting the focus outline
|
|
38266
|
-
// when we just want to make the color transparent.
|
|
38267
|
-
breadcrumbs: "rgba(255, 255, 255, 0.7)"
|
|
38268
|
-
};
|
|
38269
|
-
const borderRadius = 4;
|
|
38270
|
-
const breadcrumbStyles = {
|
|
38271
|
-
color: colors.breadcrumbs,
|
|
37810
|
+
// TODO: can we use WB typography?
|
|
37811
|
+
const bodyXsmallBold = {
|
|
37812
|
+
// For emphasized metadata, descriptions, etc
|
|
38272
37813
|
fontFamily: "inherit",
|
|
38273
37814
|
fontSize: 15,
|
|
38274
37815
|
fontWeight: "bold",
|
|
38275
|
-
|
|
38276
|
-
lineHeight: "19px",
|
|
38277
|
-
textTransform: "uppercase",
|
|
38278
|
-
// Disable subpixel antialiasing for OSX (improves light on dark text)
|
|
38279
|
-
MozOsxFontSmoothing: "grayscale",
|
|
38280
|
-
WebkitFontSmoothing: "antialiased"
|
|
38281
|
-
};
|
|
38282
|
-
const fonts = {
|
|
38283
|
-
// The body of the page is setup to use 'Helvetica' by default and
|
|
38284
|
-
// 'Lato' if/once it downloads. For your elements to follow this
|
|
38285
|
-
// pattern, all you need is to make the text in your element
|
|
38286
|
-
// inherit from the body using the "inherit" value.
|
|
38287
|
-
regular: "inherit"
|
|
38288
|
-
};
|
|
38289
|
-
const typography = {
|
|
38290
|
-
// For subject names
|
|
38291
|
-
subjectHeadingDesktop: {
|
|
38292
|
-
fontFamily: "inherit",
|
|
38293
|
-
fontSize: 50,
|
|
38294
|
-
fontWeight: "bold",
|
|
38295
|
-
lineHeight: "61px"
|
|
38296
|
-
},
|
|
38297
|
-
subjectHeadingMobile: {
|
|
38298
|
-
fontFamily: "inherit",
|
|
38299
|
-
fontSize: 35,
|
|
38300
|
-
fontWeight: "bold",
|
|
38301
|
-
lineHeight: "37px"
|
|
38302
|
-
},
|
|
38303
|
-
// For the most important thing on the page
|
|
38304
|
-
conceptHeadingDesktop: {
|
|
38305
|
-
fontFamily: "inherit",
|
|
38306
|
-
fontSize: 35,
|
|
38307
|
-
fontWeight: "bold",
|
|
38308
|
-
lineHeight: "37px"
|
|
38309
|
-
},
|
|
38310
|
-
conceptHeadingMobile: {
|
|
38311
|
-
fontFamily: "inherit",
|
|
38312
|
-
fontSize: 23,
|
|
38313
|
-
fontWeight: "bold",
|
|
38314
|
-
lineHeight: "27px"
|
|
38315
|
-
},
|
|
38316
|
-
// For sections or modules
|
|
38317
|
-
subheadingDesktop: {
|
|
38318
|
-
fontFamily: "inherit",
|
|
38319
|
-
fontSize: 23,
|
|
38320
|
-
fontWeight: "bold",
|
|
38321
|
-
lineHeight: "27px"
|
|
38322
|
-
},
|
|
38323
|
-
subheadingMobile: {
|
|
38324
|
-
fontFamily: "inherit",
|
|
38325
|
-
fontSize: 20,
|
|
38326
|
-
fontWeight: "bold",
|
|
38327
|
-
lineHeight: "24px"
|
|
38328
|
-
},
|
|
38329
|
-
smallSubheadingDesktop: {
|
|
38330
|
-
fontFamily: "inherit",
|
|
38331
|
-
fontSize: 20,
|
|
38332
|
-
lineHeight: 1.25
|
|
38333
|
-
},
|
|
38334
|
-
smallSubheadingMobile: {
|
|
38335
|
-
fontFamily: "inherit",
|
|
38336
|
-
fontSize: 15,
|
|
38337
|
-
lineHeight: 1.25
|
|
38338
|
-
},
|
|
38339
|
-
// For callouts
|
|
38340
|
-
smallHeading: {
|
|
38341
|
-
color: colors.gray25,
|
|
38342
|
-
fontFamily: "inherit",
|
|
38343
|
-
fontSize: 17,
|
|
38344
|
-
fontWeight: "bold",
|
|
38345
|
-
lineHeight: "23px"
|
|
38346
|
-
},
|
|
38347
|
-
smallHeadingMobile: {
|
|
38348
|
-
color: colors.gray25,
|
|
38349
|
-
fontFamily: "inherit",
|
|
38350
|
-
fontSize: 15,
|
|
38351
|
-
fontWeight: "bold",
|
|
38352
|
-
lineHeight: "18px"
|
|
38353
|
-
},
|
|
38354
|
-
// Accent headings
|
|
38355
|
-
accentHeading: {
|
|
38356
|
-
color: colors.gray68,
|
|
38357
|
-
fontFamily: "inherit",
|
|
38358
|
-
fontSize: 15,
|
|
38359
|
-
fontWeight: "bold",
|
|
38360
|
-
letterSpacing: 0.8,
|
|
38361
|
-
lineHeight: "19px",
|
|
38362
|
-
textTransform: "uppercase"
|
|
38363
|
-
},
|
|
38364
|
-
bodyLarge: {
|
|
38365
|
-
// For articles with multiple paragraphs
|
|
38366
|
-
fontFamily: fonts.regular,
|
|
38367
|
-
fontSize: 20,
|
|
38368
|
-
lineHeight: "30px"
|
|
38369
|
-
},
|
|
38370
|
-
bodySmall: {
|
|
38371
|
-
// For small blocks of copy
|
|
38372
|
-
fontFamily: fonts.regular,
|
|
38373
|
-
fontSize: 17,
|
|
38374
|
-
fontWeight: "normal",
|
|
38375
|
-
lineHeight: "23px"
|
|
38376
|
-
},
|
|
38377
|
-
bodySmallBold: {
|
|
38378
|
-
// For small blocks of copy
|
|
38379
|
-
fontFamily: fonts.regular,
|
|
38380
|
-
fontSize: 17,
|
|
38381
|
-
fontWeight: "bold",
|
|
38382
|
-
lineHeight: "23px"
|
|
38383
|
-
},
|
|
38384
|
-
bodyXsmall: {
|
|
38385
|
-
// For metadata, descriptions, etc
|
|
38386
|
-
fontFamily: fonts.regular,
|
|
38387
|
-
fontSize: 15,
|
|
38388
|
-
lineHeight: "22px"
|
|
38389
|
-
},
|
|
38390
|
-
bodyXsmallBold: {
|
|
38391
|
-
// For emphasized metadata, descriptions, etc
|
|
38392
|
-
fontFamily: "inherit",
|
|
38393
|
-
fontSize: 15,
|
|
38394
|
-
fontWeight: "bold",
|
|
38395
|
-
lineHeight: "22px"
|
|
38396
|
-
},
|
|
38397
|
-
breadcrumb: breadcrumbStyles,
|
|
38398
|
-
// For in-page tabs, breadcrumbs
|
|
38399
|
-
breadcrumbSmall: _extends({}, breadcrumbStyles, {
|
|
38400
|
-
fontSize: 12,
|
|
38401
|
-
lineHeight: "13px"
|
|
38402
|
-
}),
|
|
38403
|
-
labelLarge: {
|
|
38404
|
-
// For chiclets and thumbnail titles
|
|
38405
|
-
fontFamily: "inherit",
|
|
38406
|
-
fontSize: 23,
|
|
38407
|
-
fontWeight: "bold",
|
|
38408
|
-
lineHeight: "27px"
|
|
38409
|
-
},
|
|
38410
|
-
labelMedium: {
|
|
38411
|
-
// For chiclets and thumbnail titles
|
|
38412
|
-
fontFamily: "inherit",
|
|
38413
|
-
fontSize: 15,
|
|
38414
|
-
fontWeight: "bold",
|
|
38415
|
-
lineHeight: "18px"
|
|
38416
|
-
},
|
|
38417
|
-
labelSmall: {
|
|
38418
|
-
// Generally used with labelLarge, for breadcrumbs in thumbnails
|
|
38419
|
-
fontFamily: fonts.regular,
|
|
38420
|
-
fontSize: 12,
|
|
38421
|
-
lineHeight: "14px"
|
|
38422
|
-
},
|
|
38423
|
-
caption: {
|
|
38424
|
-
// For image captions
|
|
38425
|
-
fontFamily: fonts.regular,
|
|
38426
|
-
fontSize: 14,
|
|
38427
|
-
fontStyle: "italic",
|
|
38428
|
-
lineHeight: "17px"
|
|
38429
|
-
},
|
|
38430
|
-
desktopScalingOnMobile: {
|
|
38431
|
-
// For when you need Mobile Safari and friends to stick to desktop
|
|
38432
|
-
// sizes
|
|
38433
|
-
MozTextSizeAdjust: "100%",
|
|
38434
|
-
MsTextSizeAdjust: "100%",
|
|
38435
|
-
WebkitTextSizeAdjust: "100%"
|
|
38436
|
-
},
|
|
38437
|
-
// TODO (josh): This should move to within <ModalHeader>
|
|
38438
|
-
modalSubtitle: {
|
|
38439
|
-
fontSize: 12,
|
|
38440
|
-
lineHeight: 1.65,
|
|
38441
|
-
// NOTE (josh): Font smoothing used here to create a 'medium' weight
|
|
38442
|
-
// font, between normal and bold, on webkit browsers.
|
|
38443
|
-
// This prop is an a11y risk when used on non-bold text, since it
|
|
38444
|
-
// makes text very thin, but it's fine on bold text.
|
|
38445
|
-
WebkitFontSmoothing: "antialiased",
|
|
38446
|
-
fontWeight: "bold"
|
|
38447
|
-
},
|
|
38448
|
-
// HACK(kevinb): temporary wonder blocks styles for header only
|
|
38449
|
-
// TODO(kevinb): use components from wonder-blocks-typography instead
|
|
38450
|
-
wonderBlocksHeader: {
|
|
38451
|
-
paddingLeft: 16,
|
|
38452
|
-
paddingRight: 16,
|
|
38453
|
-
paddingBottom: 24,
|
|
38454
|
-
paddingTop: 34,
|
|
38455
|
-
[mediaQueries.mdOrLarger]: {
|
|
38456
|
-
paddingBottom: 32
|
|
38457
|
-
}
|
|
38458
|
-
},
|
|
38459
|
-
// HACK(kevinb): temporary wonder blocks styles for header only
|
|
38460
|
-
// TODO(kevinb): use components from wonder-blocks-typography instead
|
|
38461
|
-
wonderBlocksTitle: {
|
|
38462
|
-
color: colors.white,
|
|
38463
|
-
fontWeight: 900,
|
|
38464
|
-
// "Black" weight
|
|
38465
|
-
fontSize: 28,
|
|
38466
|
-
lineHeight: "32px",
|
|
38467
|
-
margin: 0,
|
|
38468
|
-
[mediaQueries.mdOrLarger]: {
|
|
38469
|
-
fontSize: 36,
|
|
38470
|
-
lineHeight: "40px"
|
|
38471
|
-
}
|
|
38472
|
-
},
|
|
38473
|
-
// HACK(kevinb): temporary wonder blocks styles for header only
|
|
38474
|
-
// TODO(kevinb): use components from wonder-blocks-typography instead
|
|
38475
|
-
wonderBlocksLabelLarge: {
|
|
38476
|
-
fontSize: 16,
|
|
38477
|
-
lineHeight: "20px",
|
|
38478
|
-
fontWeight: 700 // Bold
|
|
38479
|
-
}
|
|
37816
|
+
lineHeight: "22px"
|
|
38480
37817
|
};
|
|
38481
37818
|
|
|
38482
|
-
var globalStyles = /*#__PURE__*/Object.freeze({
|
|
38483
|
-
__proto__: null,
|
|
38484
|
-
colors: colors,
|
|
38485
|
-
borderRadius: borderRadius,
|
|
38486
|
-
fonts: fonts,
|
|
38487
|
-
typography: typography
|
|
38488
|
-
});
|
|
38489
|
-
|
|
38490
37819
|
const AnswerChoices = props => {
|
|
38491
37820
|
const {
|
|
38492
37821
|
strings
|
|
@@ -39322,7 +38651,7 @@ class LabelImage extends React.Component {
|
|
|
39322
38651
|
const promptString = isMobile ? multipleAnswers ? strings.tapMultiple : strings.tapSingle : multipleAnswers ? strings.clickMultiple : strings.clickSingle;
|
|
39323
38652
|
const choicesString = strings.choices;
|
|
39324
38653
|
return /*#__PURE__*/React.createElement("div", {
|
|
39325
|
-
className: classNames("perseus-label-image-widget-instructions", css(styles$a.instructions))
|
|
38654
|
+
className: classNames$1("perseus-label-image-widget-instructions", css(styles$a.instructions))
|
|
39326
38655
|
}, /*#__PURE__*/React.createElement("div", {
|
|
39327
38656
|
className: css(styles$a.instructionsCaption)
|
|
39328
38657
|
}, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React.createElement("div", {
|
|
@@ -39388,7 +38717,7 @@ const styles$a = StyleSheet.create({
|
|
|
39388
38717
|
instructions: {
|
|
39389
38718
|
paddingBottom: 16
|
|
39390
38719
|
},
|
|
39391
|
-
instructionsCaption: _extends({},
|
|
38720
|
+
instructionsCaption: _extends({}, bodyXsmallBold, {
|
|
39392
38721
|
paddingBottom: 16
|
|
39393
38722
|
}),
|
|
39394
38723
|
instructionsChoices: {
|
|
@@ -40659,7 +39988,7 @@ class Matrix extends React.Component {
|
|
|
40659
39988
|
const highlightedCol = Math.max(cursorCol, matrixSize[1] - 1);
|
|
40660
39989
|
const bracketHeight = (highlightedRow + 1) * (INPUT_HEIGHT + 2 * INPUT_MARGIN);
|
|
40661
39990
|
const bracketOffset = (highlightedCol + 1) * (INPUT_WIDTH + 2 * INPUT_MARGIN);
|
|
40662
|
-
const className = classNames({
|
|
39991
|
+
const className = classNames$1({
|
|
40663
39992
|
"perseus-matrix": true,
|
|
40664
39993
|
"static-mode": this.props.static,
|
|
40665
39994
|
"the-matrix": this.state.enterTheMatrix >= 5
|
|
@@ -43224,9 +42553,9 @@ const makeSafeUrl = (urlString, locale) => {
|
|
|
43224
42553
|
};
|
|
43225
42554
|
const styles$6 = StyleSheet.create({
|
|
43226
42555
|
widgetContainer: {
|
|
43227
|
-
borderRadius:
|
|
42556
|
+
borderRadius: 6,
|
|
43228
42557
|
borderWidth: 1,
|
|
43229
|
-
borderColor:
|
|
42558
|
+
borderColor: "#CCC",
|
|
43230
42559
|
padding: spacing.medium_16,
|
|
43231
42560
|
paddingBottom: 0
|
|
43232
42561
|
},
|
|
@@ -44543,7 +43872,7 @@ const VideoTranscriptLink = props => {
|
|
|
44543
43872
|
} = props;
|
|
44544
43873
|
const {
|
|
44545
43874
|
useVideo
|
|
44546
|
-
} =
|
|
43875
|
+
} = useDependencies();
|
|
44547
43876
|
const [id, kind] = IS_URL$1.test(location) ? [getYoutubeId(location), "YOUTUBE_ID"] : [location, "READABLE_ID"];
|
|
44548
43877
|
// The result value conforms to the wonder-blocks-data `Result` type
|
|
44549
43878
|
// which is used by our GraphQL framework.
|
|
@@ -44717,7 +44046,7 @@ const init = function init(options) {
|
|
|
44717
44046
|
|
|
44718
44047
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44719
44048
|
const libName = "@khanacademy/perseus";
|
|
44720
|
-
const libVersion = "
|
|
44049
|
+
const libVersion = "41.0.0";
|
|
44721
44050
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44722
44051
|
|
|
44723
44052
|
const apiVersion = {
|
|
@@ -44849,7 +44178,7 @@ class ArticleRenderer extends React.Component {
|
|
|
44849
44178
|
const apiOptions = _extends({}, ApiOptions.defaults, this.props.apiOptions, {
|
|
44850
44179
|
isArticle: true
|
|
44851
44180
|
});
|
|
44852
|
-
const classes = classNames({
|
|
44181
|
+
const classes = classNames$1({
|
|
44853
44182
|
"framework-perseus": true,
|
|
44854
44183
|
"perseus-article": true,
|
|
44855
44184
|
// NOTE(charlie): For exercises, this is applied outside of Perseus
|
|
@@ -44929,7 +44258,7 @@ class HintRenderer extends React.Component {
|
|
|
44929
44258
|
const {
|
|
44930
44259
|
isMobile
|
|
44931
44260
|
} = apiOptions;
|
|
44932
|
-
const classNames
|
|
44261
|
+
const classNames = classNames$1("hint", !isMobile && "perseus-hint-renderer", isMobile && css(styles$3.newHint), isMobile && lastRendered && css(styles$3.lastRenderedNewHint), lastHint && "last-hint", lastRendered && "last-rendered", className);
|
|
44933
44262
|
|
|
44934
44263
|
// TODO(charlie): Allowing `customKeypad` would require that we
|
|
44935
44264
|
// extend `ItemRenderer` to support nested inputs in the `HintsRenderer`.
|
|
@@ -44943,7 +44272,7 @@ class HintRenderer extends React.Component {
|
|
|
44943
44272
|
/*#__PURE__*/
|
|
44944
44273
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
44945
44274
|
React.createElement("div", {
|
|
44946
|
-
className: classNames
|
|
44275
|
+
className: classNames,
|
|
44947
44276
|
tabIndex: "-1"
|
|
44948
44277
|
}, !apiOptions.isMobile && /*#__PURE__*/React.createElement("span", {
|
|
44949
44278
|
className: "perseus-sr-only"
|
|
@@ -44996,7 +44325,7 @@ const styles$3 = StyleSheet.create({
|
|
|
44996
44325
|
},
|
|
44997
44326
|
lastRenderedNewHint: {
|
|
44998
44327
|
marginBottom: 0,
|
|
44999
|
-
borderLeftColor: kaGreen
|
|
44328
|
+
borderLeftColor: kaGreen
|
|
45000
44329
|
}
|
|
45001
44330
|
});
|
|
45002
44331
|
|
|
@@ -45147,9 +44476,9 @@ class HintsRenderer extends React.Component {
|
|
|
45147
44476
|
} = apiOptions;
|
|
45148
44477
|
const showGetAnotherHint = getAnotherHint && hintsVisible > 0 && hintsVisible < this.props.hints.length;
|
|
45149
44478
|
const hintRatioCopy = `(${hintsVisible}/${this.props.hints.length})`;
|
|
45150
|
-
const classNames
|
|
44479
|
+
const classNames = classNames$1(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$2.mobileHintStylesHintsRenderer));
|
|
45151
44480
|
return /*#__PURE__*/React.createElement("div", {
|
|
45152
|
-
className: classNames
|
|
44481
|
+
className: classNames
|
|
45153
44482
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React.createElement("div", {
|
|
45154
44483
|
className: css(styles$2.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
45155
44484
|
}, this.context.strings.hints), hints, showGetAnotherHint && /*#__PURE__*/React.createElement("button", {
|
|
@@ -45186,7 +44515,7 @@ const styles$2 = StyleSheet.create({
|
|
|
45186
44515
|
fontSize: "100%",
|
|
45187
44516
|
fontFamily: "inherit",
|
|
45188
44517
|
fontWeight: "bold",
|
|
45189
|
-
color: kaGreen
|
|
44518
|
+
color: kaGreen,
|
|
45190
44519
|
padding: 0,
|
|
45191
44520
|
position: "relative"
|
|
45192
44521
|
},
|
|
@@ -45581,28 +44910,6 @@ const ref = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.cre
|
|
|
45581
44910
|
ref: ref
|
|
45582
44911
|
}))));
|
|
45583
44912
|
|
|
45584
|
-
const devices = {
|
|
45585
|
-
PHONE: "phone",
|
|
45586
|
-
TABLET: "tablet",
|
|
45587
|
-
DESKTOP: "desktop"
|
|
45588
|
-
};
|
|
45589
|
-
|
|
45590
|
-
// How many pixels do we reserve on the right-hand side of a preview
|
|
45591
|
-
// for displaying lint indicators? This space needs to be reserved
|
|
45592
|
-
// in DeviceFramer, but it is actually allocated in PerseusFrame
|
|
45593
|
-
const lintGutterWidth = 36;
|
|
45594
|
-
|
|
45595
|
-
// How wide a border does PerseusFrame draw? We need to allocate enough
|
|
45596
|
-
// space for it in DeviceFramer.
|
|
45597
|
-
const perseusFrameBorderWidth = 1;
|
|
45598
|
-
|
|
45599
|
-
var constants = /*#__PURE__*/Object.freeze({
|
|
45600
|
-
__proto__: null,
|
|
45601
|
-
devices: devices,
|
|
45602
|
-
lintGutterWidth: lintGutterWidth,
|
|
45603
|
-
perseusFrameBorderWidth: perseusFrameBorderWidth
|
|
45604
|
-
});
|
|
45605
|
-
|
|
45606
44913
|
/**
|
|
45607
44914
|
* Traverses a {content, widgets, images} renderer props object,
|
|
45608
44915
|
* such as `itemData.question`
|
|
@@ -48289,5 +47596,17 @@ const EditorJsonify = {
|
|
|
48289
47596
|
}
|
|
48290
47597
|
};
|
|
48291
47598
|
|
|
48292
|
-
|
|
47599
|
+
/**
|
|
47600
|
+
* Main entry point
|
|
47601
|
+
*/
|
|
47602
|
+
const GrapherUtil = {
|
|
47603
|
+
allTypes,
|
|
47604
|
+
DEFAULT_GRAPHER_PROPS,
|
|
47605
|
+
chooseType,
|
|
47606
|
+
defaultPlotProps,
|
|
47607
|
+
getEquationString,
|
|
47608
|
+
typeToButton
|
|
47609
|
+
};
|
|
47610
|
+
|
|
47611
|
+
export { ApiOptions, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, dependencies as Dependencies, EditorJsonify, Expression, GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusExpressionAnswerFormConsidered, PerseusI18nContext, PerseusI18nContextProvider, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ref as ServerItemRenderer, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, widgets$1 as Widgets, addWidget, apiVersion, bodyXsmallBold, buildEmptyItemTreeForShape, buildMapper, components, containerSizeClass, contentHasWidgetType, convertWidgetNameToEnum, displaySigFigs, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestInteractiveGraphWidget, generateTestNumericInputWidget, generateTestPerseusItem, generateTestRadioWidget, genericPerseusItemData, getAngleCoords, getAnswerFromUserInput, getAnswersFromWidgets, getCircleCoords, getClockwiseAngle, getCorrectAnswerForWidgetId, getImagesWithoutAltData, getInteractiveBoxFromSizeClass, getLineCoords, getLinearSystemCoords, getPointCoords, getPolygonCoords, getQuadraticCoords, getSegmentCoords, getSinusoidCoords, getValidWidgetIds, getWidgetFromWidgetMap, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetTypeByWidgetId, getWidgetsFromWidgetMap, getWidgetsMapFromItemData, iconChevronDown, iconTrash, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, isWidgetIdInContent, isWrongAnswerSupported, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, lockedFigureColors, lockedFigureFillStyles, makeSafeUrl, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, shouldHaveIndividualAnswer, traverse, usePerseusI18n, violatingWidgets, allWidgets as widgets };
|
|
48293
47612
|
//# sourceMappingURL=index.js.map
|