@khanacademy/perseus-editor 14.1.3 → 14.3.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/util.d.ts +0 -14
- package/dist/es/index.js +1542 -1450
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +1375 -1274
- package/dist/index.js.map +1 -1
- package/dist/{components → widgets/interactive-graph-editor/components}/graph-points-count-selector.d.ts +1 -1
- package/dist/{components → widgets/interactive-graph-editor/components}/graph-type-selector.d.ts +1 -0
- package/dist/{components → widgets/interactive-graph-editor/components}/interactive-graph-description.d.ts +1 -1
- package/dist/widgets/interactive-graph-editor/interactive-graph-editor.d.ts +281 -128
- package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-figure-settings-actions.d.ts +1 -1
- package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-figure-settings.d.ts +2 -0
- package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-figures-section.d.ts +3 -2
- package/dist/widgets/interactive-graph-editor/locked-figures/locked-label-settings.d.ts +35 -0
- package/dist/widgets/interactive-graph-editor/locked-figures/util.d.ts +9 -0
- package/dist/widgets/interactive-graph-editor/start-coords/start-coords-angle.d.ts +9 -0
- package/dist/widgets/interactive-graph-editor/start-coords/start-coords-circle.d.ts +12 -0
- package/dist/{components → widgets/interactive-graph-editor/start-coords}/start-coords-line.d.ts +2 -2
- package/dist/{components → widgets/interactive-graph-editor/start-coords}/start-coords-multiline.d.ts +2 -2
- package/dist/{components → widgets/interactive-graph-editor/start-coords}/start-coords-point.d.ts +2 -2
- package/dist/{components → widgets/interactive-graph-editor/start-coords}/start-coords-quadratic.d.ts +2 -2
- package/dist/{components → widgets/interactive-graph-editor/start-coords}/start-coords-settings.d.ts +2 -1
- package/dist/widgets/interactive-graph-editor/start-coords/start-coords-sinusoid.d.ts +9 -0
- package/dist/widgets/interactive-graph-editor/start-coords/types.d.ts +24 -0
- package/dist/widgets/interactive-graph-editor/start-coords/util.d.ts +8 -0
- package/package.json +2 -2
- package/dist/components/graph-locked-figures/locked-label-settings.d.ts +0 -17
- package/dist/components/start-coords-angle.d.ts +0 -8
- package/dist/components/start-coords-circle.d.ts +0 -11
- package/dist/components/start-coords-sinusoid.d.ts +0 -8
- /package/dist/{components → widgets/interactive-graph-editor/components}/interactive-graph-correct-answer.d.ts +0 -0
- /package/dist/{components → widgets/interactive-graph-editor/components}/interactive-graph-settings.d.ts +0 -0
- /package/dist/{components → widgets/interactive-graph-editor/components}/segment-count-selector.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/color-select.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/color-swatch.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/defining-point-settings.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/ellipse-swatch.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/labeled-row.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/labeled-switch.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/line-stroke-select.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/line-swatch.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-ellipse-settings.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-figure-select.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-function-examples.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-function-settings.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-line-settings.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-point-settings.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-polygon-settings.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/locked-vector-settings.d.ts +0 -0
- /package/dist/{components/graph-locked-figures → widgets/interactive-graph-editor/locked-figures}/polygon-swatch.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
|
|
|
26
26
|
var mathInput = require('@khanacademy/math-input');
|
|
27
27
|
var kmath = require('@khanacademy/kmath');
|
|
28
28
|
var wonderBlocksDropdown = require('@khanacademy/wonder-blocks-dropdown');
|
|
29
|
+
var Banner = require('@khanacademy/wonder-blocks-banner');
|
|
29
30
|
var wonderBlocksAccordion = require('@khanacademy/wonder-blocks-accordion');
|
|
30
31
|
var IconButton = require('@khanacademy/wonder-blocks-icon-button');
|
|
31
32
|
var caretDoubleDownIcon = require('@phosphor-icons/core/bold/caret-double-down-bold.svg');
|
|
@@ -35,13 +36,12 @@ var caretUpIcon = require('@phosphor-icons/core/bold/caret-up-bold.svg');
|
|
|
35
36
|
var trashIcon = require('@phosphor-icons/core/bold/trash-bold.svg');
|
|
36
37
|
var copyIcon = require('@phosphor-icons/core/assets/regular/copy.svg');
|
|
37
38
|
var autoPasteIcon = require('@phosphor-icons/core/assets/regular/note-pencil.svg');
|
|
39
|
+
var plusCircle = require('@phosphor-icons/core/regular/plus-circle.svg');
|
|
38
40
|
var arrowFatDown = require('@phosphor-icons/core/regular/arrow-fat-down.svg');
|
|
39
41
|
var arrowFatLeft = require('@phosphor-icons/core/regular/arrow-fat-left.svg');
|
|
40
42
|
var arrowFatRight = require('@phosphor-icons/core/regular/arrow-fat-right.svg');
|
|
41
43
|
var arrowFatUp = require('@phosphor-icons/core/regular/arrow-fat-up.svg');
|
|
42
44
|
var minusCircle = require('@phosphor-icons/core/regular/minus-circle.svg');
|
|
43
|
-
var plusCircle = require('@phosphor-icons/core/regular/plus-circle.svg');
|
|
44
|
-
var Banner = require('@khanacademy/wonder-blocks-banner');
|
|
45
45
|
var arrowCounterClockwise = require('@phosphor-icons/core/bold/arrow-counter-clockwise-bold.svg');
|
|
46
46
|
|
|
47
47
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -76,6 +76,7 @@ var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
|
|
|
76
76
|
var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
|
|
77
77
|
var KAS__namespace = /*#__PURE__*/_interopNamespace(KAS);
|
|
78
78
|
var Button__default = /*#__PURE__*/_interopDefaultLegacy(Button);
|
|
79
|
+
var Banner__default = /*#__PURE__*/_interopDefaultLegacy(Banner);
|
|
79
80
|
var IconButton__default = /*#__PURE__*/_interopDefaultLegacy(IconButton);
|
|
80
81
|
var caretDoubleDownIcon__default = /*#__PURE__*/_interopDefaultLegacy(caretDoubleDownIcon);
|
|
81
82
|
var caretDoubleUpIcon__default = /*#__PURE__*/_interopDefaultLegacy(caretDoubleUpIcon);
|
|
@@ -84,18 +85,17 @@ var caretUpIcon__default = /*#__PURE__*/_interopDefaultLegacy(caretUpIcon);
|
|
|
84
85
|
var trashIcon__default = /*#__PURE__*/_interopDefaultLegacy(trashIcon);
|
|
85
86
|
var copyIcon__default = /*#__PURE__*/_interopDefaultLegacy(copyIcon);
|
|
86
87
|
var autoPasteIcon__default = /*#__PURE__*/_interopDefaultLegacy(autoPasteIcon);
|
|
88
|
+
var plusCircle__default = /*#__PURE__*/_interopDefaultLegacy(plusCircle);
|
|
87
89
|
var arrowFatDown__default = /*#__PURE__*/_interopDefaultLegacy(arrowFatDown);
|
|
88
90
|
var arrowFatLeft__default = /*#__PURE__*/_interopDefaultLegacy(arrowFatLeft);
|
|
89
91
|
var arrowFatRight__default = /*#__PURE__*/_interopDefaultLegacy(arrowFatRight);
|
|
90
92
|
var arrowFatUp__default = /*#__PURE__*/_interopDefaultLegacy(arrowFatUp);
|
|
91
93
|
var minusCircle__default = /*#__PURE__*/_interopDefaultLegacy(minusCircle);
|
|
92
|
-
var plusCircle__default = /*#__PURE__*/_interopDefaultLegacy(plusCircle);
|
|
93
|
-
var Banner__default = /*#__PURE__*/_interopDefaultLegacy(Banner);
|
|
94
94
|
var arrowCounterClockwise__default = /*#__PURE__*/_interopDefaultLegacy(arrowCounterClockwise);
|
|
95
95
|
|
|
96
96
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
97
97
|
const libName = "@khanacademy/perseus-editor";
|
|
98
|
-
const libVersion = "14.
|
|
98
|
+
const libVersion = "14.3.0";
|
|
99
99
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
100
100
|
|
|
101
101
|
function _extends() {
|
|
@@ -29585,39 +29585,96 @@ function invariant(condition, message) {
|
|
|
29585
29585
|
throw new Error(value);
|
|
29586
29586
|
}
|
|
29587
29587
|
|
|
29588
|
-
|
|
29589
|
-
|
|
29590
|
-
|
|
29591
|
-
|
|
29592
|
-
|
|
29593
|
-
|
|
29594
|
-
|
|
29595
|
-
|
|
29596
|
-
|
|
29597
|
-
|
|
29598
|
-
|
|
29599
|
-
|
|
29600
|
-
|
|
29601
|
-
|
|
29602
|
-
|
|
29603
|
-
|
|
29604
|
-
}
|
|
29588
|
+
const UNLIMITED = "unlimited";
|
|
29589
|
+
// Parses a string (ostensibly from some UI element that only supports string
|
|
29590
|
+
// types, such as a <select />) into a numeric point count or the special sigil
|
|
29591
|
+
// "unlimited". Note that 0 is a special case, and means "unlimited".
|
|
29592
|
+
const parsePointCount = points => {
|
|
29593
|
+
const parsed = parseInt(points, 10);
|
|
29594
|
+
if (isNaN(parsed)) {
|
|
29595
|
+
return UNLIMITED;
|
|
29596
|
+
}
|
|
29597
|
+
return parsed === 0 ? UNLIMITED : parsed;
|
|
29598
|
+
};
|
|
29599
|
+
|
|
29600
|
+
const GraphPointsCountSelector = _ref => {
|
|
29601
|
+
let {
|
|
29602
|
+
numPoints = 1,
|
|
29603
|
+
onChange
|
|
29604
|
+
} = _ref;
|
|
29605
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
29606
|
+
selectedValue: `${numPoints}`,
|
|
29607
|
+
onChange: newValue => {
|
|
29608
|
+
onChange(parsePointCount(newValue));
|
|
29609
|
+
}
|
|
29610
|
+
// Never uses placeholder, always has value
|
|
29611
|
+
,
|
|
29612
|
+
placeholder: "",
|
|
29613
|
+
style: styles$J.singleSelectShort
|
|
29614
|
+
}, [...[...Array(7).keys()].map(n => /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29615
|
+
key: n,
|
|
29616
|
+
value: `${n}`,
|
|
29617
|
+
label: `${n} point${n > 1 ? "s" : ""}`
|
|
29618
|
+
})), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29619
|
+
key: "unlimited",
|
|
29620
|
+
value: UNLIMITED,
|
|
29621
|
+
label: "unlimited"
|
|
29622
|
+
})]);
|
|
29605
29623
|
};
|
|
29606
29624
|
const styles$J = aphrodite.StyleSheet.create({
|
|
29607
|
-
|
|
29608
|
-
|
|
29609
|
-
|
|
29610
|
-
|
|
29611
|
-
|
|
29612
|
-
|
|
29613
|
-
|
|
29614
|
-
|
|
29615
|
-
|
|
29616
|
-
|
|
29617
|
-
|
|
29618
|
-
|
|
29619
|
-
|
|
29620
|
-
|
|
29625
|
+
singleSelectShort: {
|
|
29626
|
+
// Non-standard spacing, but it's the smallest we can go
|
|
29627
|
+
// without running into styling issues with the dropdown.
|
|
29628
|
+
height: 26
|
|
29629
|
+
}
|
|
29630
|
+
});
|
|
29631
|
+
|
|
29632
|
+
const GraphTypeSelector = props => {
|
|
29633
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
29634
|
+
selectedValue: props.graphType,
|
|
29635
|
+
onChange: props.onChange,
|
|
29636
|
+
placeholder: "Select an answer type",
|
|
29637
|
+
style: styles$I.singleSelectShort
|
|
29638
|
+
}, props.showNoneOption && /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29639
|
+
value: "none",
|
|
29640
|
+
label: "None"
|
|
29641
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29642
|
+
value: "linear",
|
|
29643
|
+
label: "Linear function"
|
|
29644
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29645
|
+
value: "quadratic",
|
|
29646
|
+
label: "Quadratic function"
|
|
29647
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29648
|
+
value: "sinusoid",
|
|
29649
|
+
label: "Sinusoid function"
|
|
29650
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29651
|
+
value: "circle",
|
|
29652
|
+
label: "Circle"
|
|
29653
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29654
|
+
value: "point",
|
|
29655
|
+
label: "Point(s)"
|
|
29656
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29657
|
+
value: "linear-system",
|
|
29658
|
+
label: "Linear System"
|
|
29659
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29660
|
+
value: "polygon",
|
|
29661
|
+
label: "Polygon"
|
|
29662
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29663
|
+
value: "segment",
|
|
29664
|
+
label: "Line Segment(s)"
|
|
29665
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29666
|
+
value: "ray",
|
|
29667
|
+
label: "Ray"
|
|
29668
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
29669
|
+
value: "angle",
|
|
29670
|
+
label: "Angle"
|
|
29671
|
+
}));
|
|
29672
|
+
};
|
|
29673
|
+
const styles$I = aphrodite.StyleSheet.create({
|
|
29674
|
+
singleSelectShort: {
|
|
29675
|
+
// Non-standard spacing, but it's the smallest we can go
|
|
29676
|
+
// without running into styling issues with the dropdown.
|
|
29677
|
+
height: 26
|
|
29621
29678
|
}
|
|
29622
29679
|
});
|
|
29623
29680
|
|
|
@@ -29629,11 +29686,11 @@ function Heading(_ref) {
|
|
|
29629
29686
|
onToggle
|
|
29630
29687
|
} = _ref;
|
|
29631
29688
|
return /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
29632
|
-
style: [styles$
|
|
29689
|
+
style: [styles$H.container, !isCollapsible && styles$H.notClickable],
|
|
29633
29690
|
disabled: !isCollapsible,
|
|
29634
29691
|
onClick: () => isCollapsible && onToggle?.(!isOpen)
|
|
29635
29692
|
}, () => /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
29636
|
-
style: styles$
|
|
29693
|
+
style: styles$H.heading
|
|
29637
29694
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, {
|
|
29638
29695
|
style: {
|
|
29639
29696
|
fontSize: 14,
|
|
@@ -29643,7 +29700,7 @@ function Heading(_ref) {
|
|
|
29643
29700
|
isExpanded: isOpen
|
|
29644
29701
|
})));
|
|
29645
29702
|
}
|
|
29646
|
-
const styles$
|
|
29703
|
+
const styles$H = aphrodite.StyleSheet.create({
|
|
29647
29704
|
container: {
|
|
29648
29705
|
marginTop: wonderBlocksTokens.spacing.small_12,
|
|
29649
29706
|
// NOTE(jeremy): This is the inverse of the @editorPadding CSS
|
|
@@ -29667,348 +29724,765 @@ const styles$I = aphrodite.StyleSheet.create({
|
|
|
29667
29724
|
}
|
|
29668
29725
|
});
|
|
29669
29726
|
|
|
29670
|
-
function
|
|
29671
|
-
|
|
29672
|
-
|
|
29673
|
-
|
|
29674
|
-
|
|
29675
|
-
|
|
29676
|
-
|
|
29677
|
-
|
|
29678
|
-
|
|
29679
|
-
|
|
29680
|
-
|
|
29681
|
-
|
|
29682
|
-
|
|
29683
|
-
|
|
29684
|
-
|
|
29685
|
-
|
|
29686
|
-
|
|
29687
|
-
|
|
29688
|
-
|
|
29689
|
-
|
|
29690
|
-
|
|
29691
|
-
// `preventScroll` option otherwise.
|
|
29692
|
-
//
|
|
29693
|
-
// focusOptions documentation:
|
|
29694
|
-
//
|
|
29695
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
|
|
29696
|
-
//
|
|
29697
|
-
// Note that there could be cases where we want default focus() behavior.
|
|
29698
|
-
// One that comes to mind is a dropdown with a long list of options that
|
|
29699
|
-
// might be rendered off screen when opened. With this workaround the
|
|
29700
|
-
// selected option would not be scrolled into view if the option is near
|
|
29701
|
-
// the end of the list. We're not aware of any uses of the dropdown where
|
|
29702
|
-
// this is an issue, however, so there isn't currently a way to out of the
|
|
29703
|
-
// `preventScroll` behavior.
|
|
29704
|
-
|
|
29705
|
-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element'.
|
|
29706
|
-
element.focus({
|
|
29707
|
-
preventScroll: true
|
|
29708
|
-
});
|
|
29709
|
-
}
|
|
29710
|
-
const DEFAULT_COLOR = "grayH";
|
|
29711
|
-
function getDefaultFigureForType(type) {
|
|
29712
|
-
switch (type) {
|
|
29713
|
-
case "point":
|
|
29714
|
-
return {
|
|
29715
|
-
type: "point",
|
|
29716
|
-
coord: [0, 0],
|
|
29717
|
-
color: DEFAULT_COLOR,
|
|
29718
|
-
filled: true
|
|
29719
|
-
};
|
|
29720
|
-
case "line":
|
|
29721
|
-
return {
|
|
29722
|
-
type: "line",
|
|
29723
|
-
kind: "line",
|
|
29724
|
-
points: [getDefaultFigureForType("point"), {
|
|
29725
|
-
...getDefaultFigureForType("point"),
|
|
29726
|
-
coord: [2, 2]
|
|
29727
|
-
}],
|
|
29728
|
-
color: DEFAULT_COLOR,
|
|
29729
|
-
lineStyle: "solid",
|
|
29730
|
-
showPoint1: false,
|
|
29731
|
-
showPoint2: false
|
|
29732
|
-
};
|
|
29733
|
-
case "vector":
|
|
29734
|
-
return {
|
|
29735
|
-
type: "vector",
|
|
29736
|
-
points: [[0, 0], [2, 2]],
|
|
29737
|
-
color: DEFAULT_COLOR
|
|
29738
|
-
};
|
|
29739
|
-
case "ellipse":
|
|
29740
|
-
return {
|
|
29741
|
-
type: "ellipse",
|
|
29742
|
-
center: [0, 0],
|
|
29743
|
-
radius: [1, 1],
|
|
29744
|
-
angle: 0,
|
|
29745
|
-
color: DEFAULT_COLOR,
|
|
29746
|
-
fillStyle: "none",
|
|
29747
|
-
strokeStyle: "solid"
|
|
29748
|
-
};
|
|
29749
|
-
case "polygon":
|
|
29750
|
-
return {
|
|
29751
|
-
type: "polygon",
|
|
29752
|
-
points: [[0, 2], [-1, 0], [1, 0]],
|
|
29753
|
-
color: DEFAULT_COLOR,
|
|
29754
|
-
showVertices: false,
|
|
29755
|
-
fillStyle: "none",
|
|
29756
|
-
strokeStyle: "solid"
|
|
29757
|
-
};
|
|
29758
|
-
case "function":
|
|
29759
|
-
return {
|
|
29760
|
-
type: "function",
|
|
29761
|
-
color: DEFAULT_COLOR,
|
|
29762
|
-
strokeStyle: "solid",
|
|
29763
|
-
equation: "x^2",
|
|
29764
|
-
directionalAxis: "x"
|
|
29765
|
-
};
|
|
29766
|
-
case "label":
|
|
29767
|
-
return {
|
|
29768
|
-
type: "label",
|
|
29769
|
-
coord: [0, 0],
|
|
29770
|
-
text: "",
|
|
29771
|
-
color: DEFAULT_COLOR,
|
|
29772
|
-
size: "medium"
|
|
29773
|
-
};
|
|
29774
|
-
default:
|
|
29775
|
-
throw new wonderStuffCore.UnreachableCaseError(type);
|
|
29776
|
-
}
|
|
29777
|
-
}
|
|
29778
|
-
function degreeToRadian(degrees) {
|
|
29779
|
-
return degrees / 180 * Math.PI;
|
|
29780
|
-
}
|
|
29781
|
-
function radianToDegree(radians) {
|
|
29782
|
-
return radians / Math.PI * 180;
|
|
29783
|
-
}
|
|
29784
|
-
function getDefaultGraphStartCoords(graph, range, step) {
|
|
29785
|
-
switch (graph.type) {
|
|
29786
|
-
case "linear":
|
|
29787
|
-
case "ray":
|
|
29788
|
-
return perseus.getLineCoords({
|
|
29789
|
-
...graph,
|
|
29790
|
-
startCoords: undefined
|
|
29791
|
-
}, range, step);
|
|
29792
|
-
case "segment":
|
|
29793
|
-
return perseus.getSegmentCoords({
|
|
29794
|
-
...graph,
|
|
29795
|
-
startCoords: undefined
|
|
29796
|
-
}, range, step);
|
|
29797
|
-
case "linear-system":
|
|
29798
|
-
return perseus.getLinearSystemCoords({
|
|
29799
|
-
...graph,
|
|
29800
|
-
startCoords: undefined
|
|
29801
|
-
}, range, step);
|
|
29802
|
-
case "circle":
|
|
29803
|
-
const startCoords = perseus.getCircleCoords({
|
|
29804
|
-
...graph,
|
|
29805
|
-
startCoords: undefined
|
|
29806
|
-
});
|
|
29807
|
-
const radius = kmath.vector.length(kmath.vector.subtract(startCoords.radiusPoint, startCoords.center));
|
|
29808
|
-
return {
|
|
29809
|
-
center: startCoords.center,
|
|
29810
|
-
radius
|
|
29811
|
-
};
|
|
29812
|
-
case "sinusoid":
|
|
29813
|
-
return perseus.getSinusoidCoords({
|
|
29814
|
-
...graph,
|
|
29815
|
-
startCoords: undefined
|
|
29816
|
-
}, range, step);
|
|
29817
|
-
case "quadratic":
|
|
29818
|
-
return perseus.getQuadraticCoords({
|
|
29819
|
-
...graph,
|
|
29820
|
-
startCoords: undefined
|
|
29821
|
-
}, range, step);
|
|
29822
|
-
case "point":
|
|
29823
|
-
return perseus.getPointCoords({
|
|
29824
|
-
...graph,
|
|
29825
|
-
startCoords: undefined
|
|
29826
|
-
}, range, step);
|
|
29827
|
-
case "polygon":
|
|
29828
|
-
return perseus.getPolygonCoords({
|
|
29829
|
-
...graph,
|
|
29830
|
-
startCoords: undefined
|
|
29831
|
-
}, range, step);
|
|
29832
|
-
case "angle":
|
|
29833
|
-
return perseus.getAngleCoords({
|
|
29834
|
-
graph: {
|
|
29835
|
-
...graph,
|
|
29836
|
-
startCoords: undefined
|
|
29837
|
-
},
|
|
29838
|
-
range,
|
|
29839
|
-
step
|
|
29840
|
-
});
|
|
29841
|
-
default:
|
|
29842
|
-
return undefined;
|
|
29843
|
-
}
|
|
29727
|
+
function InteractiveGraphCorrectAnswer(props) {
|
|
29728
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Heading, {
|
|
29729
|
+
title: "Correct Answer",
|
|
29730
|
+
isOpen: true,
|
|
29731
|
+
isCollapsible: false
|
|
29732
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelXSmall, {
|
|
29733
|
+
style: {
|
|
29734
|
+
paddingTop: wonderBlocksTokens.spacing.xxSmall_6,
|
|
29735
|
+
paddingBottom: wonderBlocksTokens.spacing.xxSmall_6,
|
|
29736
|
+
color: wonderBlocksTokens.color.offBlack64
|
|
29737
|
+
}
|
|
29738
|
+
}, "Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.BodyMonospace, {
|
|
29739
|
+
style: {
|
|
29740
|
+
fontSize: 12,
|
|
29741
|
+
backgroundColor: "#eee",
|
|
29742
|
+
paddingInline: wonderBlocksTokens.spacing.xxSmall_6,
|
|
29743
|
+
borderColor: "#ccc",
|
|
29744
|
+
borderStyle: "solid",
|
|
29745
|
+
borderWidth: 1
|
|
29746
|
+
}
|
|
29747
|
+
}, props.equationString)), props.children));
|
|
29844
29748
|
}
|
|
29845
|
-
const getSinusoidEquation = startCoords => {
|
|
29846
|
-
// Get coefficients
|
|
29847
|
-
// It's assumed that p1 is the root and p2 is the first peak
|
|
29848
|
-
const p1 = startCoords[0];
|
|
29849
|
-
const p2 = startCoords[1];
|
|
29850
|
-
|
|
29851
|
-
// Resulting coefficients are canonical for this sine curve
|
|
29852
|
-
const amplitude = p2[1] - p1[1];
|
|
29853
|
-
const angularFrequency = Math.PI / (2 * (p2[0] - p1[0]));
|
|
29854
|
-
const phase = p1[0] * angularFrequency;
|
|
29855
|
-
const verticalOffset = p1[1];
|
|
29856
|
-
return "y = " + amplitude.toFixed(3) + "sin(" + angularFrequency.toFixed(3) + "x - " + phase.toFixed(3) + ") + " + verticalOffset.toFixed(3);
|
|
29857
|
-
};
|
|
29858
|
-
const getQuadraticEquation = startCoords => {
|
|
29859
|
-
const p1 = startCoords[0];
|
|
29860
|
-
const p2 = startCoords[1];
|
|
29861
|
-
const p3 = startCoords[2];
|
|
29862
|
-
const denom = (p1[0] - p2[0]) * (p1[0] - p3[0]) * (p2[0] - p3[0]);
|
|
29863
|
-
if (denom === 0) {
|
|
29864
|
-
// Many of the callers assume that the return value is always defined.
|
|
29865
|
-
return "Division by zero error";
|
|
29866
|
-
}
|
|
29867
|
-
const a = (p3[0] * (p2[1] - p1[1]) + p2[0] * (p1[1] - p3[1]) + p1[0] * (p3[1] - p2[1])) / denom;
|
|
29868
|
-
const b = (p3[0] * p3[0] * (p1[1] - p2[1]) + p2[0] * p2[0] * (p3[1] - p1[1]) + p1[0] * p1[0] * (p2[1] - p3[1])) / denom;
|
|
29869
|
-
const c = (p2[0] * p3[0] * (p2[0] - p3[0]) * p1[1] + p3[0] * p1[0] * (p3[0] - p1[0]) * p2[1] + p1[0] * p2[0] * (p1[0] - p2[0]) * p3[1]) / denom;
|
|
29870
|
-
return "y = " + a.toFixed(3) + "x^2 + " + b.toFixed(3) + "x + " + c.toFixed(3);
|
|
29871
|
-
};
|
|
29872
|
-
const findAngle = (point1, point2) => {
|
|
29873
|
-
const x = point1[0] - point2[0];
|
|
29874
|
-
const y = point1[1] - point2[1];
|
|
29875
|
-
return (180 + Math.atan2(-y, -x) * 180 / Math.PI + 360) % 360;
|
|
29876
|
-
};
|
|
29877
|
-
const getAngleEquation = startCoords => {
|
|
29878
|
-
const [point1, vertex, point2] = startCoords;
|
|
29879
|
-
const angle = findAngle(point2, vertex) - findAngle(point1, vertex);
|
|
29880
|
-
const roundedAngle = angle.toFixed(0);
|
|
29881
|
-
return `${roundedAngle}\u00B0 angle at (${vertex[0]}, ${vertex[1]})`;
|
|
29882
|
-
};
|
|
29883
|
-
const shouldShowStartCoordsUI = (graph, isStatic) => {
|
|
29884
|
-
// We don't show the start coords UI for static graphs, since
|
|
29885
|
-
// the coords shown for this are determined by the coords on the
|
|
29886
|
-
// "correct" graph. The start coords would not be used here.
|
|
29887
|
-
if (isStatic) {
|
|
29888
|
-
return false;
|
|
29889
|
-
}
|
|
29890
|
-
if (graph.type === "point" && graph.numPoints === "unlimited") {
|
|
29891
|
-
return false;
|
|
29892
|
-
}
|
|
29893
|
-
if (graph.type === "polygon" && (graph.numSides === "unlimited" || graph.snapTo === "angles" || graph.snapTo === "sides")) {
|
|
29894
|
-
return false;
|
|
29895
|
-
}
|
|
29896
|
-
return true;
|
|
29897
|
-
};
|
|
29898
29749
|
|
|
29899
|
-
|
|
29900
|
-
* Dropdown for selecting a locked figure to add to an interactive graph.
|
|
29901
|
-
* Locked figures are elements (points, segmeents, etc.) that are not
|
|
29902
|
-
* interactive, just present in the graph's background.
|
|
29903
|
-
*
|
|
29904
|
-
* Used in the interactive graph editor's locked figures section.
|
|
29905
|
-
*/
|
|
29906
|
-
const LockedFigureSelect = props => {
|
|
29750
|
+
function InteractiveGraphDescription(props) {
|
|
29907
29751
|
const {
|
|
29908
|
-
|
|
29752
|
+
ariaLabelValue,
|
|
29753
|
+
ariaDescriptionValue,
|
|
29909
29754
|
onChange
|
|
29910
29755
|
} = props;
|
|
29911
|
-
const
|
|
29912
|
-
|
|
29913
|
-
|
|
29914
|
-
|
|
29915
|
-
|
|
29916
|
-
|
|
29917
|
-
}, /*#__PURE__*/React__namespace.createElement(
|
|
29918
|
-
|
|
29919
|
-
|
|
29920
|
-
|
|
29921
|
-
|
|
29922
|
-
|
|
29923
|
-
|
|
29756
|
+
const [isOpen, setIsOpen] = React__namespace.useState(true);
|
|
29757
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Heading, {
|
|
29758
|
+
title: "Description",
|
|
29759
|
+
isCollapsible: true,
|
|
29760
|
+
isOpen: isOpen,
|
|
29761
|
+
onToggle: setIsOpen
|
|
29762
|
+
}), isOpen && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelXSmall, {
|
|
29763
|
+
style: styles$G.caption
|
|
29764
|
+
}, "Use these fields to describe the graph as a whole. These are used by screen readers to describe content to users who are visually impaired."), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, {
|
|
29765
|
+
tag: "label"
|
|
29766
|
+
}, "Title", /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextField, {
|
|
29767
|
+
value: ariaLabelValue,
|
|
29768
|
+
onChange: newValue => onChange({
|
|
29769
|
+
fullGraphAriaLabel: newValue
|
|
29770
|
+
}),
|
|
29771
|
+
style: styles$G.spaceAbove
|
|
29772
|
+
})), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
29773
|
+
size: wonderBlocksTokens.spacing.small_12
|
|
29774
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, {
|
|
29775
|
+
tag: "label"
|
|
29776
|
+
}, "Description", /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextArea, {
|
|
29777
|
+
rows: 8,
|
|
29778
|
+
resizeType: "vertical",
|
|
29779
|
+
value: ariaDescriptionValue,
|
|
29780
|
+
onChange: newValue => onChange({
|
|
29781
|
+
fullGraphAriaDescription: newValue
|
|
29782
|
+
}),
|
|
29783
|
+
style: styles$G.spaceAbove
|
|
29924
29784
|
}))));
|
|
29925
|
-
}
|
|
29926
|
-
const styles$
|
|
29927
|
-
|
|
29928
|
-
|
|
29785
|
+
}
|
|
29786
|
+
const styles$G = aphrodite.StyleSheet.create({
|
|
29787
|
+
caption: {
|
|
29788
|
+
color: wonderBlocksTokens.color.offBlack64,
|
|
29789
|
+
paddingTop: wonderBlocksTokens.spacing.xxSmall_6,
|
|
29790
|
+
paddingBottom: wonderBlocksTokens.spacing.xxSmall_6
|
|
29929
29791
|
},
|
|
29930
|
-
|
|
29931
|
-
|
|
29932
|
-
borderRadius: wonderBlocksTokens.spacing.xxxSmall_4
|
|
29792
|
+
spaceAbove: {
|
|
29793
|
+
marginTop: wonderBlocksTokens.spacing.xxxSmall_4
|
|
29933
29794
|
}
|
|
29934
29795
|
});
|
|
29935
29796
|
|
|
29936
|
-
|
|
29937
|
-
|
|
29938
|
-
*
|
|
29939
|
-
* This makes it so that the text field's input number updates on scroll
|
|
29940
|
-
* without scrolling the page.
|
|
29941
|
-
*
|
|
29942
|
-
* NOTE 1: Native HTML number inputs do not update the number value on scroll,
|
|
29943
|
-
* they only scroll the page. Inputs in React do NOT work this way (explanation
|
|
29944
|
-
* here: https://stackoverflow.com/a/68266494). By default, scrolling on a
|
|
29945
|
-
* focused number input in React causes BOTH the input value to change AND
|
|
29946
|
-
* the page to scroll. The behavior in this component is an improvement on
|
|
29947
|
-
* the React behavior, but it's the opposite of the native HTML behavior.
|
|
29948
|
-
*
|
|
29949
|
-
* NOTE 2: Firefox seems to have a custom override for this. Even with this
|
|
29950
|
-
* stopPropogation, Firefox matches the native HTML behavior.
|
|
29951
|
-
*/
|
|
29952
|
-
const ScrolllessNumberTextField = props => {
|
|
29953
|
-
const inputRef = React__namespace.useRef(null);
|
|
29954
|
-
React__namespace.useEffect(() => {
|
|
29955
|
-
const ref = inputRef.current;
|
|
29956
|
-
|
|
29957
|
-
// stopPropogation makes it so that the page scroll event is not
|
|
29958
|
-
// triggered when the input is focused and the user scrolls.
|
|
29959
|
-
// The input value will still change on scroll.
|
|
29960
|
-
const ignoreScroll = e => {
|
|
29961
|
-
e.stopPropagation();
|
|
29962
|
-
};
|
|
29963
|
-
ref?.addEventListener("wheel", ignoreScroll);
|
|
29964
|
-
return () => {
|
|
29965
|
-
ref?.removeEventListener("wheel", ignoreScroll);
|
|
29966
|
-
};
|
|
29967
|
-
}, [inputRef]);
|
|
29968
|
-
return /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextField, _extends({
|
|
29969
|
-
type: "number"
|
|
29970
|
-
}, props, {
|
|
29971
|
-
ref: inputRef
|
|
29972
|
-
}));
|
|
29973
|
-
};
|
|
29974
|
-
|
|
29975
|
-
const AngleInput = props => {
|
|
29797
|
+
// Renders the given children in a View laid out horizontally.
|
|
29798
|
+
const LabeledRow = props => {
|
|
29976
29799
|
const {
|
|
29977
|
-
|
|
29978
|
-
|
|
29800
|
+
children,
|
|
29801
|
+
label,
|
|
29802
|
+
labelSide = "left",
|
|
29803
|
+
style
|
|
29979
29804
|
} = props;
|
|
29980
|
-
|
|
29981
|
-
|
|
29982
|
-
|
|
29983
|
-
|
|
29984
|
-
|
|
29985
|
-
|
|
29986
|
-
|
|
29987
|
-
|
|
29988
|
-
|
|
29989
|
-
}
|
|
29990
|
-
|
|
29991
|
-
// Update the graph.
|
|
29992
|
-
onChange(degreeToRadian(newValue));
|
|
29993
|
-
}
|
|
29994
|
-
return /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
29995
|
-
tag: "label",
|
|
29996
|
-
style: styles$G.row
|
|
29997
|
-
}, "angle (degrees)", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
29998
|
-
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
29999
|
-
}), /*#__PURE__*/React__namespace.createElement(ScrolllessNumberTextField, {
|
|
30000
|
-
value: angleInput,
|
|
30001
|
-
onChange: handleAngleChange,
|
|
30002
|
-
style: styles$G.textField
|
|
30003
|
-
}), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30004
|
-
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
30005
|
-
}));
|
|
29805
|
+
return /*#__PURE__*/React__namespace.createElement("label", {
|
|
29806
|
+
className: aphrodite.css(styles$F.label)
|
|
29807
|
+
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
29808
|
+
style: [styles$F.row, style]
|
|
29809
|
+
}, labelSide === "start" || /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
|
|
29810
|
+
style: styles$F.spaceEnd
|
|
29811
|
+
}, label), children, labelSide === "end" && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
|
|
29812
|
+
style: styles$F.spaceStart
|
|
29813
|
+
}, label)));
|
|
30006
29814
|
};
|
|
30007
|
-
const styles$
|
|
29815
|
+
const styles$F = aphrodite.StyleSheet.create({
|
|
29816
|
+
label: {
|
|
29817
|
+
width: "fit-content"
|
|
29818
|
+
},
|
|
30008
29819
|
row: {
|
|
30009
|
-
display: "flex",
|
|
30010
29820
|
flexDirection: "row",
|
|
30011
|
-
|
|
29821
|
+
marginTop: wonderBlocksTokens.spacing.xSmall_8,
|
|
29822
|
+
alignItems: "center",
|
|
29823
|
+
width: "fit-content"
|
|
29824
|
+
},
|
|
29825
|
+
spaceStart: {
|
|
29826
|
+
marginInlineStart: wonderBlocksTokens.spacing.xSmall_8
|
|
29827
|
+
},
|
|
29828
|
+
spaceEnd: {
|
|
29829
|
+
marginInlineEnd: wonderBlocksTokens.spacing.xSmall_8
|
|
29830
|
+
}
|
|
29831
|
+
});
|
|
29832
|
+
|
|
29833
|
+
/* eslint-disable react/forbid-prop-types, react/no-unsafe */
|
|
29834
|
+
const {
|
|
29835
|
+
ButtonGroup: ButtonGroup$2,
|
|
29836
|
+
InfoTip: InfoTip$d,
|
|
29837
|
+
RangeInput: RangeInput$4
|
|
29838
|
+
} = perseus.components;
|
|
29839
|
+
const defaultBackgroundImage$1 = {
|
|
29840
|
+
url: null,
|
|
29841
|
+
width: 0,
|
|
29842
|
+
height: 0
|
|
29843
|
+
};
|
|
29844
|
+
function numSteps(range, step) {
|
|
29845
|
+
return Math.floor((range[1] - range[0]) / step);
|
|
29846
|
+
}
|
|
29847
|
+
class InteractiveGraphSettings extends React__namespace.Component {
|
|
29848
|
+
_isMounted = false;
|
|
29849
|
+
bgUrlRef = /*#__PURE__*/React__namespace.createRef();
|
|
29850
|
+
labelXRef = /*#__PURE__*/React__namespace.createRef();
|
|
29851
|
+
labelYRef = /*#__PURE__*/React__namespace.createRef();
|
|
29852
|
+
static stateFromProps(props) {
|
|
29853
|
+
return {
|
|
29854
|
+
labelsTextbox: props.labels,
|
|
29855
|
+
gridStepTextbox: props.gridStep,
|
|
29856
|
+
snapStepTextbox: props.snapStep,
|
|
29857
|
+
stepTextbox: props.step,
|
|
29858
|
+
rangeTextbox: props.range,
|
|
29859
|
+
// Shallow-copied clone
|
|
29860
|
+
backgroundImage: {
|
|
29861
|
+
...props.backgroundImage
|
|
29862
|
+
}
|
|
29863
|
+
};
|
|
29864
|
+
}
|
|
29865
|
+
constructor(props) {
|
|
29866
|
+
super(props);
|
|
29867
|
+
this.state = {
|
|
29868
|
+
isExpanded: true,
|
|
29869
|
+
...InteractiveGraphSettings.stateFromProps(props)
|
|
29870
|
+
};
|
|
29871
|
+
}
|
|
29872
|
+
static defaultProps = {
|
|
29873
|
+
box: [perseus.interactiveSizes.defaultBoxSizeSmall, perseus.interactiveSizes.defaultBoxSizeSmall],
|
|
29874
|
+
labels: ["x", "y"],
|
|
29875
|
+
range: [[-10, 10], [-10, 10]],
|
|
29876
|
+
step: [1, 1],
|
|
29877
|
+
gridStep: [1, 1],
|
|
29878
|
+
snapStep: [1, 1],
|
|
29879
|
+
valid: true,
|
|
29880
|
+
backgroundImage: defaultBackgroundImage$1,
|
|
29881
|
+
markings: "graph",
|
|
29882
|
+
showProtractor: false,
|
|
29883
|
+
showTooltips: false
|
|
29884
|
+
};
|
|
29885
|
+
componentDidMount() {
|
|
29886
|
+
// TODO(scottgrant): This is a hack to remove the deprecated call to
|
|
29887
|
+
// this.isMounted() but is still considered an anti-pattern.
|
|
29888
|
+
this._isMounted = true;
|
|
29889
|
+
this.changeGraph = ___default["default"].debounce(this.changeGraph, 300);
|
|
29890
|
+
}
|
|
29891
|
+
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
29892
|
+
// Make sure that state updates when switching
|
|
29893
|
+
// between different items in a multi-item editor.
|
|
29894
|
+
if (!___default["default"].isEqual(this.props.labels, nextProps.labels) || !___default["default"].isEqual(this.props.gridStep, nextProps.gridStep) || !___default["default"].isEqual(this.props.snapStep, nextProps.snapStep) || !___default["default"].isEqual(this.props.step, nextProps.step) || !___default["default"].isEqual(this.props.range, nextProps.range) || !___default["default"].isEqual(this.props.backgroundImage, nextProps.backgroundImage)) {
|
|
29895
|
+
this.setState(InteractiveGraphSettings.stateFromProps(nextProps));
|
|
29896
|
+
}
|
|
29897
|
+
}
|
|
29898
|
+
componentWillUnmount() {
|
|
29899
|
+
this._isMounted = false;
|
|
29900
|
+
}
|
|
29901
|
+
change = (() => {
|
|
29902
|
+
var _this = this;
|
|
29903
|
+
return function () {
|
|
29904
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
29905
|
+
args[_key] = arguments[_key];
|
|
29906
|
+
}
|
|
29907
|
+
return perseus.Changeable.change.apply(_this, args);
|
|
29908
|
+
};
|
|
29909
|
+
})();
|
|
29910
|
+
changeBackgroundUrl = e => {
|
|
29911
|
+
// Only continue on blur or "enter"
|
|
29912
|
+
if (e.type === "keypress" && e.key !== "Enter") {
|
|
29913
|
+
return;
|
|
29914
|
+
}
|
|
29915
|
+
const setUrl = (url, width, height) => {
|
|
29916
|
+
// Shallow-copied clone
|
|
29917
|
+
const image = {
|
|
29918
|
+
...this.props.backgroundImage
|
|
29919
|
+
};
|
|
29920
|
+
image.url = url;
|
|
29921
|
+
image.width = width;
|
|
29922
|
+
image.height = height;
|
|
29923
|
+
this.setState({
|
|
29924
|
+
backgroundImage: image
|
|
29925
|
+
}, this.changeGraph);
|
|
29926
|
+
};
|
|
29927
|
+
const url = this.bgUrlRef.current?.value;
|
|
29928
|
+
if (url) {
|
|
29929
|
+
perseus.Util.getImageSize(url, (width, height) => {
|
|
29930
|
+
if (this._isMounted) {
|
|
29931
|
+
setUrl(url, width, height);
|
|
29932
|
+
}
|
|
29933
|
+
});
|
|
29934
|
+
} else {
|
|
29935
|
+
setUrl(null, 0, 0);
|
|
29936
|
+
}
|
|
29937
|
+
};
|
|
29938
|
+
renderLabelChoices = choices => {
|
|
29939
|
+
return choices.map(nameAndValue => /*#__PURE__*/React__namespace.createElement("option", {
|
|
29940
|
+
key: nameAndValue[1],
|
|
29941
|
+
value: nameAndValue[1]
|
|
29942
|
+
}, nameAndValue[0]));
|
|
29943
|
+
};
|
|
29944
|
+
validRange = range => {
|
|
29945
|
+
const numbers = ___default["default"].every(range, function (num) {
|
|
29946
|
+
return ___default["default"].isFinite(num);
|
|
29947
|
+
});
|
|
29948
|
+
if (!numbers) {
|
|
29949
|
+
return "Range must be a valid number";
|
|
29950
|
+
}
|
|
29951
|
+
if (range[0] >= range[1]) {
|
|
29952
|
+
return "Range must have a higher number on the right";
|
|
29953
|
+
}
|
|
29954
|
+
return true;
|
|
29955
|
+
};
|
|
29956
|
+
validateStepValue = settings => {
|
|
29957
|
+
const {
|
|
29958
|
+
step,
|
|
29959
|
+
range,
|
|
29960
|
+
name,
|
|
29961
|
+
minTicks,
|
|
29962
|
+
maxTicks
|
|
29963
|
+
} = settings;
|
|
29964
|
+
const nSteps = numSteps(range, step);
|
|
29965
|
+
if (nSteps < minTicks) {
|
|
29966
|
+
return name + " is too large, there must be at least " + minTicks + " ticks.";
|
|
29967
|
+
}
|
|
29968
|
+
if (nSteps > maxTicks) {
|
|
29969
|
+
return name + " is too small, there can be at most " + maxTicks + " ticks.";
|
|
29970
|
+
}
|
|
29971
|
+
return true;
|
|
29972
|
+
};
|
|
29973
|
+
validSnapStep = (step, range) => {
|
|
29974
|
+
return this.validateStepValue({
|
|
29975
|
+
step: step,
|
|
29976
|
+
range: range,
|
|
29977
|
+
name: "Snap step",
|
|
29978
|
+
minTicks: 5,
|
|
29979
|
+
maxTicks: 60
|
|
29980
|
+
});
|
|
29981
|
+
};
|
|
29982
|
+
validGridStep = (step, range) => {
|
|
29983
|
+
return this.validateStepValue({
|
|
29984
|
+
step: step,
|
|
29985
|
+
range: range,
|
|
29986
|
+
name: "Grid step",
|
|
29987
|
+
minTicks: 3,
|
|
29988
|
+
maxTicks: 60
|
|
29989
|
+
});
|
|
29990
|
+
};
|
|
29991
|
+
validStep = (step, range) => {
|
|
29992
|
+
return this.validateStepValue({
|
|
29993
|
+
step: step,
|
|
29994
|
+
range: range,
|
|
29995
|
+
name: "Step",
|
|
29996
|
+
minTicks: 3,
|
|
29997
|
+
maxTicks: 20
|
|
29998
|
+
});
|
|
29999
|
+
};
|
|
30000
|
+
validBackgroundImageSize = image => {
|
|
30001
|
+
// Ignore empty images
|
|
30002
|
+
if (!image.url) {
|
|
30003
|
+
return true;
|
|
30004
|
+
}
|
|
30005
|
+
const validSize = image.width <= 450 && image.height <= 450;
|
|
30006
|
+
if (!validSize) {
|
|
30007
|
+
return "Image must be smaller than 450px x 450px.";
|
|
30008
|
+
}
|
|
30009
|
+
return true;
|
|
30010
|
+
};
|
|
30011
|
+
validateGraphSettings = (range, step, gridStep, snapStep, image) => {
|
|
30012
|
+
const self = this;
|
|
30013
|
+
let msg;
|
|
30014
|
+
const goodRange = ___default["default"].every(range, function (range) {
|
|
30015
|
+
msg = self.validRange(range);
|
|
30016
|
+
return msg === true;
|
|
30017
|
+
});
|
|
30018
|
+
if (!goodRange) {
|
|
30019
|
+
return msg;
|
|
30020
|
+
}
|
|
30021
|
+
const goodStep = ___default["default"].every(step, function (step, i) {
|
|
30022
|
+
msg = self.validStep(step, range[i]);
|
|
30023
|
+
return msg === true;
|
|
30024
|
+
});
|
|
30025
|
+
if (!goodStep) {
|
|
30026
|
+
return msg;
|
|
30027
|
+
}
|
|
30028
|
+
const goodGridStep = ___default["default"].every(gridStep, function (gridStep, i) {
|
|
30029
|
+
msg = self.validGridStep(gridStep, range[i]);
|
|
30030
|
+
return msg === true;
|
|
30031
|
+
});
|
|
30032
|
+
if (!goodGridStep) {
|
|
30033
|
+
return msg;
|
|
30034
|
+
}
|
|
30035
|
+
const goodSnapStep = ___default["default"].every(snapStep, function (snapStep, i) {
|
|
30036
|
+
msg = self.validSnapStep(snapStep, range[i]);
|
|
30037
|
+
return msg === true;
|
|
30038
|
+
});
|
|
30039
|
+
if (!goodSnapStep) {
|
|
30040
|
+
return msg;
|
|
30041
|
+
}
|
|
30042
|
+
const goodImageSize = this.validBackgroundImageSize(image);
|
|
30043
|
+
if (goodImageSize !== true) {
|
|
30044
|
+
msg = goodImageSize;
|
|
30045
|
+
return msg;
|
|
30046
|
+
}
|
|
30047
|
+
return true;
|
|
30048
|
+
};
|
|
30049
|
+
changeLabel = (i, e) => {
|
|
30050
|
+
const val = e.target.value;
|
|
30051
|
+
const labels = this.state.labelsTextbox.slice();
|
|
30052
|
+
labels[i] = val;
|
|
30053
|
+
this.setState({
|
|
30054
|
+
labelsTextbox: labels
|
|
30055
|
+
}, this.changeGraph);
|
|
30056
|
+
};
|
|
30057
|
+
changeRange = (i, values) => {
|
|
30058
|
+
const ranges = this.state.rangeTextbox.slice();
|
|
30059
|
+
ranges[i] = values;
|
|
30060
|
+
const step = this.state.stepTextbox.slice();
|
|
30061
|
+
const gridStep = this.state.gridStepTextbox.slice();
|
|
30062
|
+
const snapStep = this.state.snapStepTextbox.slice();
|
|
30063
|
+
const scale = perseus.Util.scaleFromExtent(ranges[i], this.props.box[i]);
|
|
30064
|
+
if (this.validRange(ranges[i]) === true) {
|
|
30065
|
+
step[i] = perseus.Util.tickStepFromExtent(ranges[i], this.props.box[i]);
|
|
30066
|
+
const gridStepValue = perseus.Util.gridStepFromTickStep(step[i], scale);
|
|
30067
|
+
if (gridStepValue) {
|
|
30068
|
+
gridStep[i] = gridStepValue;
|
|
30069
|
+
}
|
|
30070
|
+
snapStep[i] = gridStep[i] / 2;
|
|
30071
|
+
}
|
|
30072
|
+
this.setState({
|
|
30073
|
+
stepTextbox: step,
|
|
30074
|
+
gridStepTextbox: gridStep,
|
|
30075
|
+
snapStepTextbox: snapStep,
|
|
30076
|
+
rangeTextbox: ranges
|
|
30077
|
+
}, this.changeGraph);
|
|
30078
|
+
};
|
|
30079
|
+
changeStep = step => {
|
|
30080
|
+
this.setState({
|
|
30081
|
+
stepTextbox: step
|
|
30082
|
+
}, this.changeGraph);
|
|
30083
|
+
};
|
|
30084
|
+
changeSnapStep = snapStep => {
|
|
30085
|
+
this.setState({
|
|
30086
|
+
snapStepTextbox: snapStep
|
|
30087
|
+
}, this.changeGraph);
|
|
30088
|
+
};
|
|
30089
|
+
changeGridStep = gridStep => {
|
|
30090
|
+
this.setState({
|
|
30091
|
+
gridStepTextbox: gridStep,
|
|
30092
|
+
snapStepTextbox: ___default["default"].map(gridStep, function (step) {
|
|
30093
|
+
return step / 2;
|
|
30094
|
+
})
|
|
30095
|
+
}, this.changeGraph);
|
|
30096
|
+
};
|
|
30097
|
+
changeGraph = () => {
|
|
30098
|
+
const labels = this.state.labelsTextbox;
|
|
30099
|
+
const range = ___default["default"].map(this.state.rangeTextbox, function (range) {
|
|
30100
|
+
return ___default["default"].map(range, Number);
|
|
30101
|
+
});
|
|
30102
|
+
const step = ___default["default"].map(this.state.stepTextbox, Number);
|
|
30103
|
+
const gridStep = this.state.gridStepTextbox;
|
|
30104
|
+
const snapStep = this.state.snapStepTextbox;
|
|
30105
|
+
const image = this.state.backgroundImage;
|
|
30106
|
+
|
|
30107
|
+
// validationResult is either:
|
|
30108
|
+
// true -> the settings are valid
|
|
30109
|
+
// a string -> the settings are invalid, and the explanation
|
|
30110
|
+
// is contained in the string
|
|
30111
|
+
// TODO(aria): Refactor this to not be confusing
|
|
30112
|
+
const validationResult = this.validateGraphSettings(range, step, gridStep, snapStep, image);
|
|
30113
|
+
if (validationResult === true) {
|
|
30114
|
+
// either true or a string
|
|
30115
|
+
this.change({
|
|
30116
|
+
valid: true,
|
|
30117
|
+
labels: labels,
|
|
30118
|
+
range: range,
|
|
30119
|
+
step: step,
|
|
30120
|
+
gridStep: gridStep,
|
|
30121
|
+
snapStep: snapStep,
|
|
30122
|
+
backgroundImage: image
|
|
30123
|
+
});
|
|
30124
|
+
} else {
|
|
30125
|
+
this.change({
|
|
30126
|
+
valid: validationResult // a string message, not false
|
|
30127
|
+
});
|
|
30128
|
+
}
|
|
30129
|
+
};
|
|
30130
|
+
|
|
30131
|
+
render() {
|
|
30132
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Heading, {
|
|
30133
|
+
title: "Common Graph Settings",
|
|
30134
|
+
isOpen: this.state.isExpanded,
|
|
30135
|
+
isCollapsible: true,
|
|
30136
|
+
onToggle: () => this.setState({
|
|
30137
|
+
isExpanded: !this.state.isExpanded
|
|
30138
|
+
})
|
|
30139
|
+
}), this.state.isExpanded && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement("div", {
|
|
30140
|
+
className: "graph-settings"
|
|
30141
|
+
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
30142
|
+
className: "perseus-widget-row"
|
|
30143
|
+
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
30144
|
+
className: "perseus-widget-left-col"
|
|
30145
|
+
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
30146
|
+
label: "x Label"
|
|
30147
|
+
}, /*#__PURE__*/React__namespace.createElement("input", {
|
|
30148
|
+
type: "text",
|
|
30149
|
+
className: "graph-settings-axis-label",
|
|
30150
|
+
ref: this.labelXRef,
|
|
30151
|
+
onChange: e => this.changeLabel(0, e),
|
|
30152
|
+
value: this.state.labelsTextbox[0] || ""
|
|
30153
|
+
}))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
30154
|
+
className: "perseus-widget-right-col"
|
|
30155
|
+
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
30156
|
+
label: "y Label"
|
|
30157
|
+
}, /*#__PURE__*/React__namespace.createElement("input", {
|
|
30158
|
+
type: "text",
|
|
30159
|
+
className: "graph-settings-axis-label",
|
|
30160
|
+
ref: this.labelYRef,
|
|
30161
|
+
onChange: e => this.changeLabel(1, e),
|
|
30162
|
+
value: this.state.labelsTextbox[1] || ""
|
|
30163
|
+
})))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
30164
|
+
className: "perseus-widget-row"
|
|
30165
|
+
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
30166
|
+
className: "perseus-widget-left-col"
|
|
30167
|
+
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
30168
|
+
label: "x Range"
|
|
30169
|
+
}, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
|
|
30170
|
+
value: this.state.rangeTextbox[0],
|
|
30171
|
+
onChange: vals => this.changeRange(0, vals)
|
|
30172
|
+
}))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
30173
|
+
className: "perseus-widget-right-col"
|
|
30174
|
+
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
30175
|
+
label: "y Range"
|
|
30176
|
+
}, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
|
|
30177
|
+
value: this.state.rangeTextbox[1],
|
|
30178
|
+
onChange: vals => this.changeRange(1, vals)
|
|
30179
|
+
})))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
30180
|
+
className: "perseus-widget-row"
|
|
30181
|
+
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
30182
|
+
className: "perseus-widget-left-col"
|
|
30183
|
+
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
30184
|
+
label: "Tick Step"
|
|
30185
|
+
}, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
|
|
30186
|
+
value: this.state.stepTextbox,
|
|
30187
|
+
onChange: this.changeStep
|
|
30188
|
+
}))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
30189
|
+
className: "perseus-widget-right-col"
|
|
30190
|
+
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
30191
|
+
label: "Grid Step"
|
|
30192
|
+
}, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
|
|
30193
|
+
value: this.state.gridStepTextbox,
|
|
30194
|
+
onChange: this.changeGridStep
|
|
30195
|
+
})))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
30196
|
+
className: "perseus-widget-row"
|
|
30197
|
+
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
30198
|
+
className: "perseus-widget-left-col"
|
|
30199
|
+
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
30200
|
+
label: "Snap Step"
|
|
30201
|
+
}, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
|
|
30202
|
+
value: this.state.snapStepTextbox,
|
|
30203
|
+
onChange: this.changeSnapStep
|
|
30204
|
+
})))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
30205
|
+
className: "perseus-widget-row"
|
|
30206
|
+
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
30207
|
+
label: "Markings:"
|
|
30208
|
+
}, /*#__PURE__*/React__namespace.createElement(ButtonGroup$2, {
|
|
30209
|
+
value: this.props.markings,
|
|
30210
|
+
allowEmpty: false,
|
|
30211
|
+
buttons: [{
|
|
30212
|
+
value: "graph",
|
|
30213
|
+
content: "Graph"
|
|
30214
|
+
}, {
|
|
30215
|
+
value: "grid",
|
|
30216
|
+
content: "Grid"
|
|
30217
|
+
}, {
|
|
30218
|
+
value: "none",
|
|
30219
|
+
content: "None"
|
|
30220
|
+
}],
|
|
30221
|
+
onChange: this.change("markings")
|
|
30222
|
+
}))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
30223
|
+
className: "perseus-widget-left-col"
|
|
30224
|
+
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
|
|
30225
|
+
label: "Show tooltips",
|
|
30226
|
+
checked: this.props.showTooltips,
|
|
30227
|
+
onChange: value => {
|
|
30228
|
+
this.change({
|
|
30229
|
+
showTooltips: value
|
|
30230
|
+
});
|
|
30231
|
+
}
|
|
30232
|
+
}))), /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
30233
|
+
label: "Background image URL:",
|
|
30234
|
+
style: styles$E.resetSpaceTop
|
|
30235
|
+
}, /*#__PURE__*/React__namespace.createElement("input", {
|
|
30236
|
+
type: "text",
|
|
30237
|
+
className: aphrodite.css(styles$E.backgroundUrlInput),
|
|
30238
|
+
ref: this.bgUrlRef,
|
|
30239
|
+
value: this.state.backgroundImage.url || "",
|
|
30240
|
+
onChange: e => {
|
|
30241
|
+
// Shallow-copied clone
|
|
30242
|
+
const image = {
|
|
30243
|
+
...this.props.backgroundImage
|
|
30244
|
+
};
|
|
30245
|
+
image.url = e.target.value;
|
|
30246
|
+
this.setState({
|
|
30247
|
+
backgroundImage: image
|
|
30248
|
+
});
|
|
30249
|
+
},
|
|
30250
|
+
onKeyPress: this.changeBackgroundUrl,
|
|
30251
|
+
onBlur: this.changeBackgroundUrl
|
|
30252
|
+
}), /*#__PURE__*/React__namespace.createElement(InfoTip$d, null, /*#__PURE__*/React__namespace.createElement("p", null, "Create an image in graphie, or use the \"Add image\" function to create a background."))), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30253
|
+
style: styles$E.protractorSection
|
|
30254
|
+
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30255
|
+
style: styles$E.checkboxRow
|
|
30256
|
+
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
|
|
30257
|
+
label: "Show protractor",
|
|
30258
|
+
checked: this.props.showProtractor,
|
|
30259
|
+
onChange: value => {
|
|
30260
|
+
this.change({
|
|
30261
|
+
showProtractor: value
|
|
30262
|
+
});
|
|
30263
|
+
},
|
|
30264
|
+
style: styles$E.resetSpaceTop
|
|
30265
|
+
})), this.props.showProtractor && /*#__PURE__*/React__namespace.createElement(Banner__default["default"], {
|
|
30266
|
+
layout: "floating",
|
|
30267
|
+
text: "The protractor is not accessible. Please consider an alternate approach.",
|
|
30268
|
+
kind: "warning"
|
|
30269
|
+
}))));
|
|
30270
|
+
}
|
|
30271
|
+
}
|
|
30272
|
+
const styles$E = aphrodite.StyleSheet.create({
|
|
30273
|
+
resetSpaceTop: {
|
|
30274
|
+
marginTop: 0
|
|
30275
|
+
},
|
|
30276
|
+
backgroundUrlInput: {
|
|
30277
|
+
border: `1px solid ${wonderBlocksTokens.color.offBlack32}`,
|
|
30278
|
+
borderRadius: wonderBlocksTokens.spacing.xxxSmall_4,
|
|
30279
|
+
padding: wonderBlocksTokens.spacing.xxxSmall_4
|
|
30280
|
+
},
|
|
30281
|
+
checkboxRow: {
|
|
30282
|
+
flexDirection: "row",
|
|
30283
|
+
alignItems: "center",
|
|
30284
|
+
justifyContent: "space-between",
|
|
30285
|
+
marginBottom: wonderBlocksTokens.spacing.xSmall_8
|
|
30286
|
+
},
|
|
30287
|
+
protractorSection: {
|
|
30288
|
+
marginTop: wonderBlocksTokens.spacing.xSmall_8,
|
|
30289
|
+
borderTop: `1px solid ${wonderBlocksTokens.color.offBlack16}`,
|
|
30290
|
+
paddingTop: wonderBlocksTokens.spacing.xSmall_8,
|
|
30291
|
+
paddingBottom: wonderBlocksTokens.spacing.xSmall_8,
|
|
30292
|
+
borderBottom: `1px solid ${wonderBlocksTokens.color.offBlack16}`
|
|
30293
|
+
}
|
|
30294
|
+
});
|
|
30295
|
+
|
|
30296
|
+
const SegmentCountSelector = _ref => {
|
|
30297
|
+
let {
|
|
30298
|
+
numSegments = 1,
|
|
30299
|
+
onChange
|
|
30300
|
+
} = _ref;
|
|
30301
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
30302
|
+
key: "segment-select",
|
|
30303
|
+
selectedValue: `${numSegments}`
|
|
30304
|
+
// Never uses placeholder, always has value
|
|
30305
|
+
,
|
|
30306
|
+
placeholder: "",
|
|
30307
|
+
onChange: newValue => {
|
|
30308
|
+
const num = +newValue;
|
|
30309
|
+
onChange(num);
|
|
30310
|
+
},
|
|
30311
|
+
style: styles$D.singleSelectShort
|
|
30312
|
+
}, ___default["default"].range(1, 7).map(n => /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
30313
|
+
key: n,
|
|
30314
|
+
value: `${n}`,
|
|
30315
|
+
label: `${n} segment${n > 1 ? "s" : ""}`
|
|
30316
|
+
})));
|
|
30317
|
+
};
|
|
30318
|
+
const styles$D = aphrodite.StyleSheet.create({
|
|
30319
|
+
singleSelectShort: {
|
|
30320
|
+
// Non-standard spacing, but it's the smallest we can go
|
|
30321
|
+
// without running into styling issues with the dropdown.
|
|
30322
|
+
height: 26
|
|
30323
|
+
}
|
|
30324
|
+
});
|
|
30325
|
+
|
|
30326
|
+
/**
|
|
30327
|
+
* Dropdown for selecting a locked figure to add to an interactive graph.
|
|
30328
|
+
* Locked figures are elements (points, segmeents, etc.) that are not
|
|
30329
|
+
* interactive, just present in the graph's background.
|
|
30330
|
+
*
|
|
30331
|
+
* Used in the interactive graph editor's locked figures section.
|
|
30332
|
+
*/
|
|
30333
|
+
const LockedFigureSelect = props => {
|
|
30334
|
+
const {
|
|
30335
|
+
id,
|
|
30336
|
+
onChange
|
|
30337
|
+
} = props;
|
|
30338
|
+
const figureTypes = ["point", "line", "vector", "ellipse", "polygon", "function"];
|
|
30339
|
+
if (props.showLabelsFlag) {
|
|
30340
|
+
figureTypes.push("label");
|
|
30341
|
+
}
|
|
30342
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30343
|
+
style: styles$C.container
|
|
30344
|
+
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.ActionMenu, {
|
|
30345
|
+
menuText: "Add locked figure",
|
|
30346
|
+
style: styles$C.addElementSelect
|
|
30347
|
+
}, figureTypes.map(figureType => /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.ActionItem, {
|
|
30348
|
+
key: `${id}-${figureType}`,
|
|
30349
|
+
label: figureType,
|
|
30350
|
+
onClick: () => onChange(figureType)
|
|
30351
|
+
}))));
|
|
30352
|
+
};
|
|
30353
|
+
const styles$C = aphrodite.StyleSheet.create({
|
|
30354
|
+
container: {
|
|
30355
|
+
marginTop: wonderBlocksTokens.spacing.xSmall_8
|
|
30356
|
+
},
|
|
30357
|
+
addElementSelect: {
|
|
30358
|
+
backgroundColor: wonderBlocksTokens.color.fadedBlue8,
|
|
30359
|
+
borderRadius: wonderBlocksTokens.spacing.xxxSmall_4
|
|
30360
|
+
}
|
|
30361
|
+
});
|
|
30362
|
+
|
|
30363
|
+
/**
|
|
30364
|
+
* This is a custom text field of type="number" for use in Perseus Editors.
|
|
30365
|
+
*
|
|
30366
|
+
* This makes it so that the text field's input number updates on scroll
|
|
30367
|
+
* without scrolling the page.
|
|
30368
|
+
*
|
|
30369
|
+
* NOTE 1: Native HTML number inputs do not update the number value on scroll,
|
|
30370
|
+
* they only scroll the page. Inputs in React do NOT work this way (explanation
|
|
30371
|
+
* here: https://stackoverflow.com/a/68266494). By default, scrolling on a
|
|
30372
|
+
* focused number input in React causes BOTH the input value to change AND
|
|
30373
|
+
* the page to scroll. The behavior in this component is an improvement on
|
|
30374
|
+
* the React behavior, but it's the opposite of the native HTML behavior.
|
|
30375
|
+
*
|
|
30376
|
+
* NOTE 2: Firefox seems to have a custom override for this. Even with this
|
|
30377
|
+
* stopPropogation, Firefox matches the native HTML behavior.
|
|
30378
|
+
*/
|
|
30379
|
+
const ScrolllessNumberTextField = props => {
|
|
30380
|
+
const inputRef = React__namespace.useRef(null);
|
|
30381
|
+
React__namespace.useEffect(() => {
|
|
30382
|
+
const ref = inputRef.current;
|
|
30383
|
+
|
|
30384
|
+
// stopPropogation makes it so that the page scroll event is not
|
|
30385
|
+
// triggered when the input is focused and the user scrolls.
|
|
30386
|
+
// The input value will still change on scroll.
|
|
30387
|
+
const ignoreScroll = e => {
|
|
30388
|
+
e.stopPropagation();
|
|
30389
|
+
};
|
|
30390
|
+
ref?.addEventListener("wheel", ignoreScroll);
|
|
30391
|
+
return () => {
|
|
30392
|
+
ref?.removeEventListener("wheel", ignoreScroll);
|
|
30393
|
+
};
|
|
30394
|
+
}, [inputRef]);
|
|
30395
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextField, _extends({
|
|
30396
|
+
type: "number"
|
|
30397
|
+
}, props, {
|
|
30398
|
+
ref: inputRef
|
|
30399
|
+
}));
|
|
30400
|
+
};
|
|
30401
|
+
|
|
30402
|
+
function focusWithChromeStickyFocusBugWorkaround(element) {
|
|
30403
|
+
// NOTE(marksandstrom) Chrome sticky focus bug.
|
|
30404
|
+
//
|
|
30405
|
+
// There is a bug in Chrome related to sticky positioning and
|
|
30406
|
+
// focus: When a child of an element with sticky positioning is
|
|
30407
|
+
// focused with the focus() method, the scrollable area
|
|
30408
|
+
// containing that element will scroll to the top (even though
|
|
30409
|
+
// the element is already visble on the page). For a dropdown
|
|
30410
|
+
// this means that the area will be scrolled to the top when
|
|
30411
|
+
// the user interacts with the dropdown (since we actively
|
|
30412
|
+
// manage dropdown header and option focus for keyboard users).
|
|
30413
|
+
//
|
|
30414
|
+
// To work around this bug the `preventScroll` focus option is
|
|
30415
|
+
// used.
|
|
30416
|
+
//
|
|
30417
|
+
// Using `focusOptions` is an experimental browser feature
|
|
30418
|
+
// "that should not be used in production code". However, since
|
|
30419
|
+
// Chrome is the only browser we support that exhibits this
|
|
30420
|
+
// buggy behavior and using `focusOptions` works around the
|
|
30421
|
+
// bug, it is perfectly reasonable to use the feature in this
|
|
30422
|
+
// case. We are not relying on the effect of the
|
|
30423
|
+
// `preventScroll` option otherwise.
|
|
30424
|
+
//
|
|
30425
|
+
// focusOptions documentation:
|
|
30426
|
+
//
|
|
30427
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
|
|
30428
|
+
//
|
|
30429
|
+
// Note that there could be cases where we want default focus() behavior.
|
|
30430
|
+
// One that comes to mind is a dropdown with a long list of options that
|
|
30431
|
+
// might be rendered off screen when opened. With this workaround the
|
|
30432
|
+
// selected option would not be scrolled into view if the option is near
|
|
30433
|
+
// the end of the list. We're not aware of any uses of the dropdown where
|
|
30434
|
+
// this is an issue, however, so there isn't currently a way to out of the
|
|
30435
|
+
// `preventScroll` behavior.
|
|
30436
|
+
|
|
30437
|
+
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element'.
|
|
30438
|
+
element.focus({
|
|
30439
|
+
preventScroll: true
|
|
30440
|
+
});
|
|
30441
|
+
}
|
|
30442
|
+
function degreeToRadian(degrees) {
|
|
30443
|
+
return degrees / 180 * Math.PI;
|
|
30444
|
+
}
|
|
30445
|
+
function radianToDegree(radians) {
|
|
30446
|
+
return radians / Math.PI * 180;
|
|
30447
|
+
}
|
|
30448
|
+
|
|
30449
|
+
const AngleInput = props => {
|
|
30450
|
+
const {
|
|
30451
|
+
angle,
|
|
30452
|
+
onChange
|
|
30453
|
+
} = props;
|
|
30454
|
+
const [angleInput, setAngleInput] = React__namespace.useState(radianToDegree(angle).toString());
|
|
30455
|
+
function handleAngleChange(newValue) {
|
|
30456
|
+
// Update the local state (update the input field value).
|
|
30457
|
+
setAngleInput(newValue);
|
|
30458
|
+
|
|
30459
|
+
// If the new value is not a number, don't update the props.
|
|
30460
|
+
// If it's empty, keep the props the same value instead of setting to 0.
|
|
30461
|
+
if (isNaN(+newValue) || newValue === "") {
|
|
30462
|
+
return;
|
|
30463
|
+
}
|
|
30464
|
+
|
|
30465
|
+
// Update the graph.
|
|
30466
|
+
onChange(degreeToRadian(newValue));
|
|
30467
|
+
}
|
|
30468
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30469
|
+
tag: "label",
|
|
30470
|
+
style: styles$B.row
|
|
30471
|
+
}, "angle (degrees)", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30472
|
+
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
30473
|
+
}), /*#__PURE__*/React__namespace.createElement(ScrolllessNumberTextField, {
|
|
30474
|
+
value: angleInput,
|
|
30475
|
+
onChange: handleAngleChange,
|
|
30476
|
+
style: styles$B.textField
|
|
30477
|
+
}), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30478
|
+
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
30479
|
+
}));
|
|
30480
|
+
};
|
|
30481
|
+
const styles$B = aphrodite.StyleSheet.create({
|
|
30482
|
+
row: {
|
|
30483
|
+
display: "flex",
|
|
30484
|
+
flexDirection: "row",
|
|
30485
|
+
alignItems: "center"
|
|
30012
30486
|
},
|
|
30013
30487
|
textField: {
|
|
30014
30488
|
width: wonderBlocksTokens.spacing.xxxLarge_64
|
|
@@ -30053,30 +30527,30 @@ const CoordinatePairInput = props => {
|
|
|
30053
30527
|
onChange(newCoords);
|
|
30054
30528
|
}
|
|
30055
30529
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30056
|
-
style: [styles$
|
|
30530
|
+
style: [styles$A.row, style]
|
|
30057
30531
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30058
30532
|
tag: "label",
|
|
30059
|
-
style: styles$
|
|
30533
|
+
style: styles$A.row
|
|
30060
30534
|
}, labels ? labels[0] : "x coord", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30061
30535
|
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
30062
30536
|
}), /*#__PURE__*/React__namespace.createElement(ScrolllessNumberTextField, {
|
|
30063
30537
|
value: coordState[0],
|
|
30064
30538
|
onChange: newValue => handleCoordChange(newValue, 0),
|
|
30065
|
-
style: [styles$
|
|
30539
|
+
style: [styles$A.textField, error ? styles$A.errorField : undefined]
|
|
30066
30540
|
})), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30067
30541
|
size: wonderBlocksTokens.spacing.medium_16
|
|
30068
30542
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30069
30543
|
tag: "label",
|
|
30070
|
-
style: styles$
|
|
30544
|
+
style: styles$A.row
|
|
30071
30545
|
}, labels ? labels[1] : "y coord", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30072
30546
|
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
30073
30547
|
}), /*#__PURE__*/React__namespace.createElement(ScrolllessNumberTextField, {
|
|
30074
30548
|
value: coordState[1],
|
|
30075
30549
|
onChange: newValue => handleCoordChange(newValue, 1),
|
|
30076
|
-
style: [styles$
|
|
30550
|
+
style: [styles$A.textField, error ? styles$A.errorField : undefined]
|
|
30077
30551
|
})));
|
|
30078
30552
|
};
|
|
30079
|
-
const styles$
|
|
30553
|
+
const styles$A = aphrodite.StyleSheet.create({
|
|
30080
30554
|
row: {
|
|
30081
30555
|
display: "flex",
|
|
30082
30556
|
flexDirection: "row",
|
|
@@ -30109,14 +30583,14 @@ const PerseusEditorAccordion = props => {
|
|
|
30109
30583
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksAccordion.AccordionSection, {
|
|
30110
30584
|
expanded: expanded,
|
|
30111
30585
|
onToggle: onToggle,
|
|
30112
|
-
style: [styles$
|
|
30113
|
-
headerStyle: styles$
|
|
30586
|
+
style: [styles$z.container, containerStyle],
|
|
30587
|
+
headerStyle: styles$z.accordionHeader,
|
|
30114
30588
|
header: header
|
|
30115
30589
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30116
|
-
style: [styles$
|
|
30590
|
+
style: [styles$z.accordionPanel, panelStyle]
|
|
30117
30591
|
}, children)));
|
|
30118
30592
|
};
|
|
30119
|
-
const styles$
|
|
30593
|
+
const styles$z = aphrodite.StyleSheet.create({
|
|
30120
30594
|
container: {
|
|
30121
30595
|
backgroundColor: wonderBlocksTokens.color.fadedBlue8,
|
|
30122
30596
|
marginTop: wonderBlocksTokens.spacing.xSmall_8
|
|
@@ -30147,13 +30621,13 @@ const ColorSwatch = props => {
|
|
|
30147
30621
|
"aria-label":
|
|
30148
30622
|
// Don't include an aria label for decorative circles.
|
|
30149
30623
|
!decorative ? `${color}, ${filled ? "filled" : "open"}` : undefined,
|
|
30150
|
-
style: [styles$
|
|
30624
|
+
style: [styles$y.colorSwatch, {
|
|
30151
30625
|
border: `4px solid ${perseus.lockedFigureColors[color]}`,
|
|
30152
30626
|
backgroundColor: filled ? perseus.lockedFigureColors[color] : wonderBlocksTokens.color.white
|
|
30153
30627
|
}]
|
|
30154
30628
|
});
|
|
30155
30629
|
};
|
|
30156
|
-
const styles$
|
|
30630
|
+
const styles$y = aphrodite.StyleSheet.create({
|
|
30157
30631
|
colorSwatch: {
|
|
30158
30632
|
// Add a white outline so that the color swatch is visible when
|
|
30159
30633
|
// the dropdown option is highlighted with its blue background.
|
|
@@ -30172,10 +30646,10 @@ const ColorSelect = props => {
|
|
|
30172
30646
|
onChange
|
|
30173
30647
|
} = props;
|
|
30174
30648
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30175
|
-
style: [styles$
|
|
30649
|
+
style: [styles$x.row, style]
|
|
30176
30650
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30177
30651
|
tag: "label",
|
|
30178
|
-
style: styles$
|
|
30652
|
+
style: styles$x.row
|
|
30179
30653
|
}, "color", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30180
30654
|
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
30181
30655
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
@@ -30194,7 +30668,7 @@ const ColorSelect = props => {
|
|
|
30194
30668
|
})
|
|
30195
30669
|
})))));
|
|
30196
30670
|
};
|
|
30197
|
-
const styles$
|
|
30671
|
+
const styles$x = aphrodite.StyleSheet.create({
|
|
30198
30672
|
row: {
|
|
30199
30673
|
display: "flex",
|
|
30200
30674
|
flexDirection: "row",
|
|
@@ -30213,17 +30687,17 @@ const EllipseSwatch = props => {
|
|
|
30213
30687
|
} = props;
|
|
30214
30688
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30215
30689
|
"aria-label": `${color}, stroke ${strokeStyle}, fill ${fillStyle}`,
|
|
30216
|
-
style: [styles$
|
|
30690
|
+
style: [styles$w.container, {
|
|
30217
30691
|
border: `4px ${strokeStyle} ${perseus.lockedFigureColors[color]}`
|
|
30218
30692
|
}]
|
|
30219
30693
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30220
|
-
style: [styles$
|
|
30694
|
+
style: [styles$w.innerCircle, {
|
|
30221
30695
|
backgroundColor: perseus.lockedFigureColors[color],
|
|
30222
30696
|
opacity: fillStyle === "white" ? 0 : perseus.lockedFigureFillStyles[fillStyle]
|
|
30223
30697
|
}]
|
|
30224
30698
|
}));
|
|
30225
30699
|
};
|
|
30226
|
-
const styles$
|
|
30700
|
+
const styles$w = aphrodite.StyleSheet.create({
|
|
30227
30701
|
container: {
|
|
30228
30702
|
// Add a white outline so that the color swatch is visible when
|
|
30229
30703
|
// the dropdown option is highlighted with its blue background.
|
|
@@ -30249,7 +30723,7 @@ const LineStrokeSelect = props => {
|
|
|
30249
30723
|
} = props;
|
|
30250
30724
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30251
30725
|
tag: "label",
|
|
30252
|
-
style: styles$
|
|
30726
|
+
style: styles$v.lineStrokeSelect
|
|
30253
30727
|
}, "stroke", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30254
30728
|
size: wonderBlocksTokens.spacing.xxxSmall_4
|
|
30255
30729
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
@@ -30266,7 +30740,7 @@ const LineStrokeSelect = props => {
|
|
|
30266
30740
|
label: "dashed"
|
|
30267
30741
|
})));
|
|
30268
30742
|
};
|
|
30269
|
-
const styles$
|
|
30743
|
+
const styles$v = aphrodite.StyleSheet.create({
|
|
30270
30744
|
lineStrokeSelect: {
|
|
30271
30745
|
display: "flex",
|
|
30272
30746
|
flexDirection: "row",
|
|
@@ -30288,40 +30762,40 @@ const LockedFigureSettingsActions = props => {
|
|
|
30288
30762
|
onRemove
|
|
30289
30763
|
} = props;
|
|
30290
30764
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30291
|
-
style: styles$
|
|
30765
|
+
style: styles$u.container
|
|
30292
30766
|
}, /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
|
|
30293
30767
|
startIcon: trashIcon__default["default"],
|
|
30294
30768
|
"aria-label": `Delete locked ${figureType}`,
|
|
30295
30769
|
onClick: onRemove,
|
|
30296
30770
|
kind: "tertiary",
|
|
30297
|
-
style: styles$
|
|
30298
|
-
}, "Delete"), /*#__PURE__*/React__namespace.createElement(Spring, null), /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
30771
|
+
style: styles$u.deleteButton
|
|
30772
|
+
}, "Delete"), onMove && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Spring, null), /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
30299
30773
|
icon: caretDoubleUpIcon__default["default"],
|
|
30300
30774
|
size: "small",
|
|
30301
30775
|
"aria-label": `Move locked ${figureType} to the back`,
|
|
30302
30776
|
onClick: () => onMove("back"),
|
|
30303
|
-
style: styles$
|
|
30777
|
+
style: styles$u.iconButton
|
|
30304
30778
|
}), /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
30305
30779
|
icon: caretUpIcon__default["default"],
|
|
30306
30780
|
size: "small",
|
|
30307
30781
|
"aria-label": `Move locked ${figureType} backward`,
|
|
30308
30782
|
onClick: () => onMove("backward"),
|
|
30309
|
-
style: styles$
|
|
30783
|
+
style: styles$u.iconButton
|
|
30310
30784
|
}), /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
30311
30785
|
icon: caretDownIcon__default["default"],
|
|
30312
30786
|
size: "small",
|
|
30313
30787
|
"aria-label": `Move locked ${figureType} forward`,
|
|
30314
30788
|
onClick: () => onMove("forward"),
|
|
30315
|
-
style: styles$
|
|
30789
|
+
style: styles$u.iconButton
|
|
30316
30790
|
}), /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
30317
30791
|
icon: caretDoubleDownIcon__default["default"],
|
|
30318
30792
|
size: "small",
|
|
30319
30793
|
"aria-label": `Move locked ${figureType} to the front`,
|
|
30320
30794
|
onClick: () => onMove("front"),
|
|
30321
|
-
style: styles$
|
|
30322
|
-
}));
|
|
30795
|
+
style: styles$u.iconButton
|
|
30796
|
+
})));
|
|
30323
30797
|
};
|
|
30324
|
-
const styles$
|
|
30798
|
+
const styles$u = aphrodite.StyleSheet.create({
|
|
30325
30799
|
container: {
|
|
30326
30800
|
width: "100%",
|
|
30327
30801
|
flexDirection: "row",
|
|
@@ -30340,7 +30814,7 @@ const styles$z = aphrodite.StyleSheet.create({
|
|
|
30340
30814
|
});
|
|
30341
30815
|
|
|
30342
30816
|
const {
|
|
30343
|
-
InfoTip: InfoTip$
|
|
30817
|
+
InfoTip: InfoTip$c
|
|
30344
30818
|
} = perseus.components;
|
|
30345
30819
|
const LockedEllipseSettings = props => {
|
|
30346
30820
|
const {
|
|
@@ -30368,7 +30842,7 @@ const LockedEllipseSettings = props => {
|
|
|
30368
30842
|
/*#__PURE__*/
|
|
30369
30843
|
// Summary: Ellipse, center, radius, color (opacity, dashed)
|
|
30370
30844
|
React__namespace.createElement(wonderBlocksCore.View, {
|
|
30371
|
-
style: styles$
|
|
30845
|
+
style: styles$t.row
|
|
30372
30846
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, `Ellipse (${center[0]}, ${center[1]}), radius ${radius[0]}, ${radius[1]}`), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30373
30847
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
30374
30848
|
}), /*#__PURE__*/React__namespace.createElement(EllipseSwatch, {
|
|
@@ -30377,19 +30851,19 @@ const LockedEllipseSettings = props => {
|
|
|
30377
30851
|
strokeStyle: strokeStyle
|
|
30378
30852
|
}))
|
|
30379
30853
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30380
|
-
style: styles$
|
|
30854
|
+
style: styles$t.row
|
|
30381
30855
|
}, /*#__PURE__*/React__namespace.createElement(CoordinatePairInput, {
|
|
30382
30856
|
coord: center,
|
|
30383
|
-
style: styles$
|
|
30857
|
+
style: styles$t.spaceUnder,
|
|
30384
30858
|
onChange: newCoords => onChangeProps({
|
|
30385
30859
|
center: newCoords
|
|
30386
30860
|
})
|
|
30387
30861
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30388
|
-
style: styles$
|
|
30389
|
-
}, /*#__PURE__*/React__namespace.createElement(InfoTip$
|
|
30862
|
+
style: styles$t.spaceUnder
|
|
30863
|
+
}, /*#__PURE__*/React__namespace.createElement(InfoTip$c, null, "The coordinates for the center of the ellipse."))), /*#__PURE__*/React__namespace.createElement(CoordinatePairInput, {
|
|
30390
30864
|
coord: radius,
|
|
30391
30865
|
labels: ["x radius", "y radius"],
|
|
30392
|
-
style: styles$
|
|
30866
|
+
style: styles$t.spaceUnder,
|
|
30393
30867
|
onChange: newCoords => onChangeProps({
|
|
30394
30868
|
radius: newCoords
|
|
30395
30869
|
})
|
|
@@ -30401,7 +30875,7 @@ const LockedEllipseSettings = props => {
|
|
|
30401
30875
|
}), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30402
30876
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
30403
30877
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30404
|
-
style: [styles$
|
|
30878
|
+
style: [styles$t.row, styles$t.spaceUnder]
|
|
30405
30879
|
}, /*#__PURE__*/React__namespace.createElement(ColorSelect, {
|
|
30406
30880
|
selectedValue: color,
|
|
30407
30881
|
onChange: handleColorChange
|
|
@@ -30409,7 +30883,7 @@ const LockedEllipseSettings = props => {
|
|
|
30409
30883
|
size: wonderBlocksTokens.spacing.medium_16
|
|
30410
30884
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30411
30885
|
tag: "label",
|
|
30412
|
-
style: [styles$
|
|
30886
|
+
style: [styles$t.row, styles$t.truncatedWidth]
|
|
30413
30887
|
}, "fill", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30414
30888
|
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
30415
30889
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
@@ -30435,7 +30909,7 @@ const LockedEllipseSettings = props => {
|
|
|
30435
30909
|
onRemove: onRemove
|
|
30436
30910
|
}));
|
|
30437
30911
|
};
|
|
30438
|
-
const styles$
|
|
30912
|
+
const styles$t = aphrodite.StyleSheet.create({
|
|
30439
30913
|
row: {
|
|
30440
30914
|
display: "flex",
|
|
30441
30915
|
flexDirection: "row",
|
|
@@ -30456,15 +30930,15 @@ const LineSwatch = props => {
|
|
|
30456
30930
|
lineStyle
|
|
30457
30931
|
} = props;
|
|
30458
30932
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30459
|
-
style: styles$
|
|
30933
|
+
style: styles$s.container
|
|
30460
30934
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30461
30935
|
"aria-label": `${color}, ${lineStyle}`,
|
|
30462
|
-
style: [styles$
|
|
30936
|
+
style: [styles$s.lineSwatch, {
|
|
30463
30937
|
border: `5px ${lineStyle} ${perseus.lockedFigureColors[color]}`
|
|
30464
30938
|
}]
|
|
30465
30939
|
}));
|
|
30466
30940
|
};
|
|
30467
|
-
const styles$
|
|
30941
|
+
const styles$s = aphrodite.StyleSheet.create({
|
|
30468
30942
|
container: {
|
|
30469
30943
|
backgroundColor: wonderBlocksTokens.color.white,
|
|
30470
30944
|
justifyContent: "center",
|
|
@@ -30549,9 +31023,9 @@ const LockedFunctionSettings = props => {
|
|
|
30549
31023
|
expanded: props.expanded,
|
|
30550
31024
|
onToggle: props.onToggle,
|
|
30551
31025
|
header: /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30552
|
-
style: styles$
|
|
31026
|
+
style: styles$r.row
|
|
30553
31027
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, {
|
|
30554
|
-
style: styles$
|
|
31028
|
+
style: styles$r.accordionHeader
|
|
30555
31029
|
}, lineLabel), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30556
31030
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
30557
31031
|
}), /*#__PURE__*/React__namespace.createElement(LineSwatch, {
|
|
@@ -30559,7 +31033,7 @@ const LockedFunctionSettings = props => {
|
|
|
30559
31033
|
lineStyle: strokeStyle
|
|
30560
31034
|
}))
|
|
30561
31035
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30562
|
-
style: [styles$
|
|
31036
|
+
style: [styles$r.row, styles$r.spaceUnder]
|
|
30563
31037
|
}, /*#__PURE__*/React__namespace.createElement(ColorSelect, {
|
|
30564
31038
|
selectedValue: lineColor,
|
|
30565
31039
|
onChange: newValue => {
|
|
@@ -30573,14 +31047,14 @@ const LockedFunctionSettings = props => {
|
|
|
30573
31047
|
handlePropChange("strokeStyle", newValue);
|
|
30574
31048
|
}
|
|
30575
31049
|
})), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30576
|
-
style: [styles$
|
|
31050
|
+
style: [styles$r.row, styles$r.rowSpace]
|
|
30577
31051
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
30578
31052
|
selectedValue: directionalAxis,
|
|
30579
31053
|
onChange: newValue => {
|
|
30580
31054
|
handlePropChange("directionalAxis", newValue);
|
|
30581
31055
|
},
|
|
30582
31056
|
"aria-label": "equation prefix",
|
|
30583
|
-
style: [styles$
|
|
31057
|
+
style: [styles$r.dropdownLabel, styles$r.axisMenu]
|
|
30584
31058
|
// Placeholder is required, but never gets used.
|
|
30585
31059
|
,
|
|
30586
31060
|
placeholder: ""
|
|
@@ -30599,17 +31073,17 @@ const LockedFunctionSettings = props => {
|
|
|
30599
31073
|
onChange: newValue => {
|
|
30600
31074
|
handlePropChange("equation", newValue);
|
|
30601
31075
|
},
|
|
30602
|
-
style: [styles$
|
|
31076
|
+
style: [styles$r.textField]
|
|
30603
31077
|
})), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30604
|
-
style: [styles$
|
|
31078
|
+
style: [styles$r.row, styles$r.rowSpace]
|
|
30605
31079
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30606
31080
|
tag: "label",
|
|
30607
|
-
style: [styles$
|
|
31081
|
+
style: [styles$r.dropdownLabel, styles$r.domainMin]
|
|
30608
31082
|
}, `${domainRangeText} min`, /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30609
31083
|
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
30610
31084
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextField, {
|
|
30611
31085
|
type: "number",
|
|
30612
|
-
style: styles$
|
|
31086
|
+
style: styles$r.domainMinField,
|
|
30613
31087
|
value: domainEntries[0],
|
|
30614
31088
|
onChange: newValue => {
|
|
30615
31089
|
handleDomainChange(0, newValue);
|
|
@@ -30619,12 +31093,12 @@ const LockedFunctionSettings = props => {
|
|
|
30619
31093
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30620
31094
|
tag: "label",
|
|
30621
31095
|
"aria-label": `${domainRangeText} max`,
|
|
30622
|
-
style: [styles$
|
|
31096
|
+
style: [styles$r.dropdownLabel, styles$r.domainMax]
|
|
30623
31097
|
}, "max", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30624
31098
|
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
30625
31099
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextField, {
|
|
30626
31100
|
type: "number",
|
|
30627
|
-
style: styles$
|
|
31101
|
+
style: styles$r.domainMaxField,
|
|
30628
31102
|
value: domainEntries[1],
|
|
30629
31103
|
onChange: newValue => {
|
|
30630
31104
|
handleDomainChange(1, newValue);
|
|
@@ -30632,11 +31106,11 @@ const LockedFunctionSettings = props => {
|
|
|
30632
31106
|
}))), /*#__PURE__*/React__namespace.createElement(PerseusEditorAccordion, {
|
|
30633
31107
|
header: /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, "Example Functions"),
|
|
30634
31108
|
expanded: false,
|
|
30635
|
-
containerStyle: styles$
|
|
30636
|
-
panelStyle: styles$
|
|
31109
|
+
containerStyle: styles$r.exampleWorkspace,
|
|
31110
|
+
panelStyle: styles$r.exampleAccordionPanel
|
|
30637
31111
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30638
31112
|
tag: "label",
|
|
30639
|
-
style: styles$
|
|
31113
|
+
style: styles$r.dropdownLabel
|
|
30640
31114
|
}, "Choose a category", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30641
31115
|
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
30642
31116
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
@@ -30650,7 +31124,7 @@ const LockedFunctionSettings = props => {
|
|
|
30650
31124
|
label: category
|
|
30651
31125
|
});
|
|
30652
31126
|
}))), exampleCategorySelected && /*#__PURE__*/React__namespace.createElement("ul", {
|
|
30653
|
-
className: aphrodite.css(styles$
|
|
31127
|
+
className: aphrodite.css(styles$r.exampleContainer)
|
|
30654
31128
|
}, exampleContent.map((example, index) => /*#__PURE__*/React__namespace.createElement(ExampleItem, {
|
|
30655
31129
|
category: exampleCategory,
|
|
30656
31130
|
example: example,
|
|
@@ -30672,29 +31146,29 @@ const ExampleItem = props => {
|
|
|
30672
31146
|
const exampleId = React.useId();
|
|
30673
31147
|
return /*#__PURE__*/React__namespace.createElement("li", {
|
|
30674
31148
|
key: `${category}-${index}`,
|
|
30675
|
-
className: aphrodite.css(styles$
|
|
31149
|
+
className: aphrodite.css(styles$r.exampleRow)
|
|
30676
31150
|
}, /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
30677
31151
|
icon: autoPasteIcon__default["default"],
|
|
30678
31152
|
"aria-label": "paste example",
|
|
30679
31153
|
"aria-describedby": exampleId,
|
|
30680
31154
|
onClick: () => pasteEquationFn("equation", example),
|
|
30681
31155
|
size: "medium",
|
|
30682
|
-
style: styles$
|
|
31156
|
+
style: styles$r.copyPasteButton
|
|
30683
31157
|
}), /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
30684
31158
|
icon: copyIcon__default["default"],
|
|
30685
31159
|
"aria-label": "copy example",
|
|
30686
31160
|
"aria-describedby": exampleId,
|
|
30687
31161
|
onClick: () => navigator.clipboard.writeText(example),
|
|
30688
31162
|
size: "medium",
|
|
30689
|
-
style: styles$
|
|
31163
|
+
style: styles$r.copyPasteButton
|
|
30690
31164
|
}), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30691
31165
|
size: wonderBlocksTokens.spacing.xxxSmall_4
|
|
30692
31166
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30693
|
-
style: styles$
|
|
31167
|
+
style: styles$r.exampleContent,
|
|
30694
31168
|
id: exampleId
|
|
30695
31169
|
}, example));
|
|
30696
31170
|
};
|
|
30697
|
-
const styles$
|
|
31171
|
+
const styles$r = aphrodite.StyleSheet.create({
|
|
30698
31172
|
accordionHeader: {
|
|
30699
31173
|
textOverflow: "ellipsis",
|
|
30700
31174
|
// A maximum width needs to be specified in order for the ellipsis to work.
|
|
@@ -30812,15 +31286,16 @@ function LockedLabelSettings(props) {
|
|
|
30812
31286
|
expanded: expanded,
|
|
30813
31287
|
onToggle: onToggle,
|
|
30814
31288
|
header: /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30815
|
-
style: [styles$
|
|
31289
|
+
style: [styles$q.row, styles$q.accordionHeaderContainer]
|
|
30816
31290
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, "Label (", coord[0], ", ", coord[1], ")"), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30817
31291
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
30818
31292
|
}), text !== "" && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, {
|
|
30819
31293
|
style: [{
|
|
30820
31294
|
backgroundColor: wonderBlocksTokens.color.white,
|
|
30821
31295
|
color: perseus.lockedFigureColors[color]
|
|
30822
|
-
}, styles$
|
|
30823
|
-
}, text))
|
|
31296
|
+
}, styles$q.accordionHeader]
|
|
31297
|
+
}, text)),
|
|
31298
|
+
containerStyle: !onMove && styles$q.innerLabelAccordionPanel
|
|
30824
31299
|
}, /*#__PURE__*/React__namespace.createElement(CoordinatePairInput, {
|
|
30825
31300
|
coord: coord,
|
|
30826
31301
|
onChange: newCoords => {
|
|
@@ -30828,10 +31303,10 @@ function LockedLabelSettings(props) {
|
|
|
30828
31303
|
coord: newCoords
|
|
30829
31304
|
});
|
|
30830
31305
|
},
|
|
30831
|
-
style: styles$
|
|
31306
|
+
style: styles$q.spaceUnder
|
|
30832
31307
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30833
31308
|
tag: "label",
|
|
30834
|
-
style: [styles$
|
|
31309
|
+
style: [styles$q.row, styles$q.spaceUnder]
|
|
30835
31310
|
}, "TeX", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30836
31311
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
30837
31312
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextField, {
|
|
@@ -30841,20 +31316,20 @@ function LockedLabelSettings(props) {
|
|
|
30841
31316
|
text: newValue
|
|
30842
31317
|
})
|
|
30843
31318
|
})), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30844
|
-
style: styles$
|
|
30845
|
-
}, /*#__PURE__*/React__namespace.createElement(ColorSelect, {
|
|
31319
|
+
style: styles$q.row
|
|
31320
|
+
}, onMove && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(ColorSelect, {
|
|
30846
31321
|
selectedValue: color,
|
|
30847
31322
|
onChange: newColor => {
|
|
30848
31323
|
onChangeProps({
|
|
30849
31324
|
color: newColor
|
|
30850
31325
|
});
|
|
30851
31326
|
},
|
|
30852
|
-
style: styles$
|
|
31327
|
+
style: styles$q.spaceUnder
|
|
30853
31328
|
}), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30854
31329
|
size: wonderBlocksTokens.spacing.medium_16
|
|
30855
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
31330
|
+
})), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
30856
31331
|
tag: "label",
|
|
30857
|
-
style: styles$
|
|
31332
|
+
style: styles$q.row
|
|
30858
31333
|
}, "size", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30859
31334
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
30860
31335
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
@@ -30881,7 +31356,7 @@ function LockedLabelSettings(props) {
|
|
|
30881
31356
|
onRemove: onRemove
|
|
30882
31357
|
}));
|
|
30883
31358
|
}
|
|
30884
|
-
const styles$
|
|
31359
|
+
const styles$q = aphrodite.StyleSheet.create({
|
|
30885
31360
|
accordionHeaderContainer: {
|
|
30886
31361
|
// Stop the label summary from wrapping.
|
|
30887
31362
|
whiteSpace: "nowrap"
|
|
@@ -30902,6 +31377,9 @@ const styles$v = aphrodite.StyleSheet.create({
|
|
|
30902
31377
|
},
|
|
30903
31378
|
spaceUnder: {
|
|
30904
31379
|
marginBottom: wonderBlocksTokens.spacing.xSmall_8
|
|
31380
|
+
},
|
|
31381
|
+
innerLabelAccordionPanel: {
|
|
31382
|
+
backgroundColor: wonderBlocksTokens.color.white
|
|
30905
31383
|
}
|
|
30906
31384
|
});
|
|
30907
31385
|
|
|
@@ -30915,7 +31393,7 @@ const LabeledSwitch = props => {
|
|
|
30915
31393
|
const ids = wonderBlocksCore.useUniqueIdWithMock();
|
|
30916
31394
|
const switchId = ids.get("switch");
|
|
30917
31395
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30918
|
-
style: [styles$
|
|
31396
|
+
style: [styles$p.row, style]
|
|
30919
31397
|
}, /*#__PURE__*/React__namespace.createElement(Switch__default["default"], {
|
|
30920
31398
|
id: switchId,
|
|
30921
31399
|
checked: checked,
|
|
@@ -30927,7 +31405,7 @@ const LabeledSwitch = props => {
|
|
|
30927
31405
|
htmlFor: switchId
|
|
30928
31406
|
}, label));
|
|
30929
31407
|
};
|
|
30930
|
-
const styles$
|
|
31408
|
+
const styles$p = aphrodite.StyleSheet.create({
|
|
30931
31409
|
row: {
|
|
30932
31410
|
flexDirection: "row",
|
|
30933
31411
|
alignItems: "center"
|
|
@@ -30961,13 +31439,13 @@ const DefiningPointSettings = props => {
|
|
|
30961
31439
|
return /*#__PURE__*/React__namespace.createElement(PerseusEditorAccordion, {
|
|
30962
31440
|
expanded: expanded,
|
|
30963
31441
|
onToggle: onToggle,
|
|
30964
|
-
containerStyle: styles$
|
|
30965
|
-
panelStyle: styles$
|
|
31442
|
+
containerStyle: styles$o.container,
|
|
31443
|
+
panelStyle: styles$o.accordionPanel,
|
|
30966
31444
|
header:
|
|
30967
31445
|
/*#__PURE__*/
|
|
30968
31446
|
// Summary: Point, coords, color (filled/open)
|
|
30969
31447
|
React__namespace.createElement(wonderBlocksCore.View, {
|
|
30970
|
-
style: styles$
|
|
31448
|
+
style: styles$o.row
|
|
30971
31449
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, `${label || "Point"} (${coord[0]}, ${coord[1]})`), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
30972
31450
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
30973
31451
|
}), showPoint && /*#__PURE__*/React__namespace.createElement(ColorSwatch, {
|
|
@@ -30977,7 +31455,7 @@ const DefiningPointSettings = props => {
|
|
|
30977
31455
|
}, /*#__PURE__*/React__namespace.createElement(CoordinatePairInput, {
|
|
30978
31456
|
coord: coord,
|
|
30979
31457
|
error: !!error,
|
|
30980
|
-
style: styles$
|
|
31458
|
+
style: styles$o.spaceUnder,
|
|
30981
31459
|
onChange: newCoords => {
|
|
30982
31460
|
onChangeProps({
|
|
30983
31461
|
coord: newCoords
|
|
@@ -30986,12 +31464,12 @@ const DefiningPointSettings = props => {
|
|
|
30986
31464
|
}), onTogglePoint && /*#__PURE__*/React__namespace.createElement(LabeledSwitch, {
|
|
30987
31465
|
label: "show point on graph",
|
|
30988
31466
|
checked: !!showPoint,
|
|
30989
|
-
style: showPoint && styles$
|
|
31467
|
+
style: showPoint && styles$o.spaceUnder,
|
|
30990
31468
|
onChange: onTogglePoint
|
|
30991
31469
|
}), showPoint && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(ColorSelect, {
|
|
30992
31470
|
selectedValue: pointColor,
|
|
30993
31471
|
onChange: handleColorChange,
|
|
30994
|
-
style: styles$
|
|
31472
|
+
style: styles$o.spaceUnder
|
|
30995
31473
|
}), /*#__PURE__*/React__namespace.createElement(LabeledSwitch, {
|
|
30996
31474
|
label: "open point",
|
|
30997
31475
|
checked: !filled,
|
|
@@ -31002,7 +31480,7 @@ const DefiningPointSettings = props => {
|
|
|
31002
31480
|
}
|
|
31003
31481
|
})));
|
|
31004
31482
|
};
|
|
31005
|
-
const styles$
|
|
31483
|
+
const styles$o = aphrodite.StyleSheet.create({
|
|
31006
31484
|
container: {
|
|
31007
31485
|
marginTop: wonderBlocksTokens.spacing.xSmall_8,
|
|
31008
31486
|
marginBottom: 0,
|
|
@@ -31070,7 +31548,7 @@ const LockedLineSettings = props => {
|
|
|
31070
31548
|
expanded: props.expanded,
|
|
31071
31549
|
onToggle: props.onToggle,
|
|
31072
31550
|
header: /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31073
|
-
style: styles$
|
|
31551
|
+
style: styles$n.row
|
|
31074
31552
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, lineLabel), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
31075
31553
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
31076
31554
|
}), /*#__PURE__*/React__namespace.createElement(LineSwatch, {
|
|
@@ -31079,7 +31557,7 @@ const LockedLineSettings = props => {
|
|
|
31079
31557
|
}))
|
|
31080
31558
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
31081
31559
|
tag: "label",
|
|
31082
|
-
style: [styles$
|
|
31560
|
+
style: [styles$n.row, styles$n.spaceUnder]
|
|
31083
31561
|
}, "kind", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
31084
31562
|
size: wonderBlocksTokens.spacing.xxxSmall_4
|
|
31085
31563
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
@@ -31100,7 +31578,7 @@ const LockedLineSettings = props => {
|
|
|
31100
31578
|
value: "segment",
|
|
31101
31579
|
label: "segment"
|
|
31102
31580
|
}))), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31103
|
-
style: styles$
|
|
31581
|
+
style: styles$n.row
|
|
31104
31582
|
}, /*#__PURE__*/React__namespace.createElement(ColorSelect, {
|
|
31105
31583
|
selectedValue: lineColor,
|
|
31106
31584
|
onChange: handleColorChange
|
|
@@ -31112,7 +31590,7 @@ const LockedLineSettings = props => {
|
|
|
31112
31590
|
lineStyle: value
|
|
31113
31591
|
})
|
|
31114
31592
|
})), isInvalid && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
31115
|
-
style: styles$
|
|
31593
|
+
style: styles$n.errorText
|
|
31116
31594
|
}, lengthZeroStr), /*#__PURE__*/React__namespace.createElement(DefiningPointSettings, _extends({
|
|
31117
31595
|
label: "Point 1",
|
|
31118
31596
|
showPoint: showPoint1,
|
|
@@ -31137,7 +31615,7 @@ const LockedLineSettings = props => {
|
|
|
31137
31615
|
onRemove: onRemove
|
|
31138
31616
|
}));
|
|
31139
31617
|
};
|
|
31140
|
-
const styles$
|
|
31618
|
+
const styles$n = aphrodite.StyleSheet.create({
|
|
31141
31619
|
row: {
|
|
31142
31620
|
display: "flex",
|
|
31143
31621
|
flexDirection: "row",
|
|
@@ -31151,24 +31629,127 @@ const styles$s = aphrodite.StyleSheet.create({
|
|
|
31151
31629
|
}
|
|
31152
31630
|
});
|
|
31153
31631
|
|
|
31154
|
-
|
|
31155
|
-
|
|
31156
|
-
|
|
31157
|
-
|
|
31158
|
-
|
|
31159
|
-
|
|
31632
|
+
const DEFAULT_COLOR = "grayH";
|
|
31633
|
+
function getDefaultFigureForType(type) {
|
|
31634
|
+
switch (type) {
|
|
31635
|
+
case "point":
|
|
31636
|
+
return {
|
|
31637
|
+
type: "point",
|
|
31638
|
+
coord: [0, 0],
|
|
31639
|
+
color: DEFAULT_COLOR,
|
|
31640
|
+
filled: true,
|
|
31641
|
+
labels: []
|
|
31642
|
+
};
|
|
31643
|
+
case "line":
|
|
31644
|
+
return {
|
|
31645
|
+
type: "line",
|
|
31646
|
+
kind: "line",
|
|
31647
|
+
points: [getDefaultFigureForType("point"), {
|
|
31648
|
+
...getDefaultFigureForType("point"),
|
|
31649
|
+
coord: [2, 2]
|
|
31650
|
+
}],
|
|
31651
|
+
color: DEFAULT_COLOR,
|
|
31652
|
+
lineStyle: "solid",
|
|
31653
|
+
showPoint1: false,
|
|
31654
|
+
showPoint2: false
|
|
31655
|
+
};
|
|
31656
|
+
case "vector":
|
|
31657
|
+
return {
|
|
31658
|
+
type: "vector",
|
|
31659
|
+
points: [[0, 0], [2, 2]],
|
|
31660
|
+
color: DEFAULT_COLOR
|
|
31661
|
+
};
|
|
31662
|
+
case "ellipse":
|
|
31663
|
+
return {
|
|
31664
|
+
type: "ellipse",
|
|
31665
|
+
center: [0, 0],
|
|
31666
|
+
radius: [1, 1],
|
|
31667
|
+
angle: 0,
|
|
31668
|
+
color: DEFAULT_COLOR,
|
|
31669
|
+
fillStyle: "none",
|
|
31670
|
+
strokeStyle: "solid"
|
|
31671
|
+
};
|
|
31672
|
+
case "polygon":
|
|
31673
|
+
return {
|
|
31674
|
+
type: "polygon",
|
|
31675
|
+
points: [[0, 2], [-1, 0], [1, 0]],
|
|
31676
|
+
color: DEFAULT_COLOR,
|
|
31677
|
+
showVertices: false,
|
|
31678
|
+
fillStyle: "none",
|
|
31679
|
+
strokeStyle: "solid"
|
|
31680
|
+
};
|
|
31681
|
+
case "function":
|
|
31682
|
+
return {
|
|
31683
|
+
type: "function",
|
|
31684
|
+
color: DEFAULT_COLOR,
|
|
31685
|
+
strokeStyle: "solid",
|
|
31686
|
+
equation: "x^2",
|
|
31687
|
+
directionalAxis: "x"
|
|
31688
|
+
};
|
|
31689
|
+
case "label":
|
|
31690
|
+
return {
|
|
31691
|
+
type: "label",
|
|
31692
|
+
coord: [0, 0],
|
|
31693
|
+
text: "",
|
|
31694
|
+
color: DEFAULT_COLOR,
|
|
31695
|
+
size: "medium"
|
|
31696
|
+
};
|
|
31697
|
+
default:
|
|
31698
|
+
throw new wonderStuffCore.UnreachableCaseError(type);
|
|
31699
|
+
}
|
|
31700
|
+
}
|
|
31701
|
+
|
|
31160
31702
|
const LockedPointSettings = props => {
|
|
31161
31703
|
const {
|
|
31704
|
+
flags,
|
|
31162
31705
|
coord,
|
|
31163
31706
|
color: pointColor,
|
|
31164
31707
|
filled = true,
|
|
31708
|
+
labels,
|
|
31165
31709
|
onChangeProps,
|
|
31166
31710
|
onMove,
|
|
31167
31711
|
onRemove
|
|
31168
31712
|
} = props;
|
|
31169
31713
|
function handleColorChange(newValue) {
|
|
31170
|
-
|
|
31714
|
+
const newProps = {
|
|
31715
|
+
color: newValue
|
|
31716
|
+
};
|
|
31717
|
+
|
|
31718
|
+
// Update the color of the all labels to match the point
|
|
31719
|
+
newProps.labels = labels.map(label => ({
|
|
31720
|
+
...label,
|
|
31171
31721
|
color: newValue
|
|
31722
|
+
}));
|
|
31723
|
+
onChangeProps(newProps);
|
|
31724
|
+
}
|
|
31725
|
+
function handleCoordChange(newCoord) {
|
|
31726
|
+
const xOffset = newCoord[0] - coord[0];
|
|
31727
|
+
const yOffset = newCoord[1] - coord[1];
|
|
31728
|
+
const newProps = {
|
|
31729
|
+
coord: newCoord
|
|
31730
|
+
};
|
|
31731
|
+
|
|
31732
|
+
// Update the coord by the same amount as the point for all labels
|
|
31733
|
+
newProps.labels = labels.map(label => ({
|
|
31734
|
+
...label,
|
|
31735
|
+
coord: [label.coord[0] + xOffset, label.coord[1] + yOffset]
|
|
31736
|
+
}));
|
|
31737
|
+
onChangeProps(newProps);
|
|
31738
|
+
}
|
|
31739
|
+
function handleLabelChange(updatedLabel, labelIndex) {
|
|
31740
|
+
const updatedLabels = [...labels];
|
|
31741
|
+
updatedLabels[labelIndex] = {
|
|
31742
|
+
...labels[labelIndex],
|
|
31743
|
+
...updatedLabel
|
|
31744
|
+
};
|
|
31745
|
+
onChangeProps({
|
|
31746
|
+
labels: updatedLabels
|
|
31747
|
+
});
|
|
31748
|
+
}
|
|
31749
|
+
function handleLabelRemove(labelIndex) {
|
|
31750
|
+
const updatedLabels = labels.filter((_, index) => index !== labelIndex);
|
|
31751
|
+
onChangeProps({
|
|
31752
|
+
labels: updatedLabels
|
|
31172
31753
|
});
|
|
31173
31754
|
}
|
|
31174
31755
|
return /*#__PURE__*/React__namespace.createElement(PerseusEditorAccordion, {
|
|
@@ -31178,7 +31759,7 @@ const LockedPointSettings = props => {
|
|
|
31178
31759
|
/*#__PURE__*/
|
|
31179
31760
|
// Summary: Point, coords, color (filled/open)
|
|
31180
31761
|
React__namespace.createElement(wonderBlocksCore.View, {
|
|
31181
|
-
style: styles$
|
|
31762
|
+
style: styles$m.row
|
|
31182
31763
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, `Point (${coord[0]}, ${coord[1]})`), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
31183
31764
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
31184
31765
|
}), /*#__PURE__*/React__namespace.createElement(ColorSwatch, {
|
|
@@ -31186,17 +31767,13 @@ const LockedPointSettings = props => {
|
|
|
31186
31767
|
filled: filled
|
|
31187
31768
|
}))
|
|
31188
31769
|
}, /*#__PURE__*/React__namespace.createElement(CoordinatePairInput, {
|
|
31189
|
-
coord: coord,
|
|
31190
|
-
style: styles$
|
|
31191
|
-
onChange:
|
|
31192
|
-
onChangeProps({
|
|
31193
|
-
coord: newCoord
|
|
31194
|
-
});
|
|
31195
|
-
}
|
|
31770
|
+
coord: coord,
|
|
31771
|
+
style: styles$m.spaceUnder,
|
|
31772
|
+
onChange: handleCoordChange
|
|
31196
31773
|
}), /*#__PURE__*/React__namespace.createElement(ColorSelect, {
|
|
31197
31774
|
selectedValue: pointColor,
|
|
31198
31775
|
onChange: handleColorChange,
|
|
31199
|
-
style: styles$
|
|
31776
|
+
style: styles$m.spaceUnder
|
|
31200
31777
|
}), /*#__PURE__*/React__namespace.createElement(LabeledSwitch, {
|
|
31201
31778
|
label: "open point",
|
|
31202
31779
|
checked: !filled,
|
|
@@ -31204,20 +31781,53 @@ const LockedPointSettings = props => {
|
|
|
31204
31781
|
onChangeProps({
|
|
31205
31782
|
filled: !newValue
|
|
31206
31783
|
});
|
|
31784
|
+
},
|
|
31785
|
+
style: styles$m.spaceUnder
|
|
31786
|
+
}), flags?.["mafs"]?.["locked-point-labels"] && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, labels.map((label, labelIndex) => /*#__PURE__*/React__namespace.createElement(LockedLabelSettings, _extends({}, label, {
|
|
31787
|
+
expanded: true,
|
|
31788
|
+
onChangeProps: newLabel => {
|
|
31789
|
+
handleLabelChange(newLabel, labelIndex);
|
|
31790
|
+
},
|
|
31791
|
+
onRemove: () => {
|
|
31792
|
+
handleLabelRemove(labelIndex);
|
|
31207
31793
|
}
|
|
31208
|
-
}), /*#__PURE__*/React__namespace.createElement(
|
|
31794
|
+
}))), /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
|
|
31795
|
+
kind: "tertiary",
|
|
31796
|
+
startIcon: plusCircle__default["default"],
|
|
31797
|
+
onClick: () => {
|
|
31798
|
+
const newLabel = {
|
|
31799
|
+
...getDefaultFigureForType("label"),
|
|
31800
|
+
// Place the label at the same position
|
|
31801
|
+
// as the point. Add a small offset to
|
|
31802
|
+
// avoid crowding.
|
|
31803
|
+
coord: [coord[0] + 0.5,
|
|
31804
|
+
// Additional offset for each label so
|
|
31805
|
+
// they don't overlap.
|
|
31806
|
+
coord[1] - 1 * labels?.length],
|
|
31807
|
+
// Default to the same color as the point
|
|
31808
|
+
color: pointColor
|
|
31809
|
+
};
|
|
31810
|
+
onChangeProps({
|
|
31811
|
+
labels: [...labels, newLabel]
|
|
31812
|
+
});
|
|
31813
|
+
},
|
|
31814
|
+
style: styles$m.addButton
|
|
31815
|
+
}, "Add visible label")), /*#__PURE__*/React__namespace.createElement(LockedFigureSettingsActions, {
|
|
31209
31816
|
figureType: props.type,
|
|
31210
31817
|
onMove: onMove,
|
|
31211
31818
|
onRemove: onRemove
|
|
31212
31819
|
}));
|
|
31213
31820
|
};
|
|
31214
|
-
const styles$
|
|
31821
|
+
const styles$m = aphrodite.StyleSheet.create({
|
|
31215
31822
|
row: {
|
|
31216
31823
|
flexDirection: "row",
|
|
31217
31824
|
alignItems: "center"
|
|
31218
31825
|
},
|
|
31219
31826
|
spaceUnder: {
|
|
31220
31827
|
marginBottom: wonderBlocksTokens.spacing.xSmall_8
|
|
31828
|
+
},
|
|
31829
|
+
addButton: {
|
|
31830
|
+
alignSelf: "start"
|
|
31221
31831
|
}
|
|
31222
31832
|
});
|
|
31223
31833
|
|
|
@@ -31229,17 +31839,17 @@ const PolygonSwatch = props => {
|
|
|
31229
31839
|
} = props;
|
|
31230
31840
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31231
31841
|
"aria-label": `${color}, stroke ${strokeStyle}, fill ${fillStyle}`,
|
|
31232
|
-
style: [styles$
|
|
31842
|
+
style: [styles$l.container, {
|
|
31233
31843
|
border: `4px ${strokeStyle} ${perseus.lockedFigureColors[color]}`
|
|
31234
31844
|
}]
|
|
31235
31845
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31236
|
-
style: [styles$
|
|
31846
|
+
style: [styles$l.innerSquare, {
|
|
31237
31847
|
backgroundColor: perseus.lockedFigureColors[color],
|
|
31238
31848
|
opacity: fillStyle === "white" ? 0 : perseus.lockedFigureFillStyles[fillStyle]
|
|
31239
31849
|
}]
|
|
31240
31850
|
}));
|
|
31241
31851
|
};
|
|
31242
|
-
const styles$
|
|
31852
|
+
const styles$l = aphrodite.StyleSheet.create({
|
|
31243
31853
|
container: {
|
|
31244
31854
|
// Add a white outline so that the color swatch is visible when
|
|
31245
31855
|
// the dropdown option is highlighted with its blue background.
|
|
@@ -31317,7 +31927,7 @@ const LockedPolygonSettings = props => {
|
|
|
31317
31927
|
/*#__PURE__*/
|
|
31318
31928
|
// Summary: Polygon, number of sides, style swatch
|
|
31319
31929
|
React__namespace.createElement(wonderBlocksCore.View, {
|
|
31320
|
-
style: styles$
|
|
31930
|
+
style: styles$k.row
|
|
31321
31931
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, `Polygon, ${points.length} sides`), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
31322
31932
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
31323
31933
|
}), /*#__PURE__*/React__namespace.createElement(PolygonSwatch, {
|
|
@@ -31326,7 +31936,7 @@ const LockedPolygonSettings = props => {
|
|
|
31326
31936
|
strokeStyle: strokeStyle
|
|
31327
31937
|
}))
|
|
31328
31938
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31329
|
-
style: [styles$
|
|
31939
|
+
style: [styles$k.row, styles$k.spaceUnder]
|
|
31330
31940
|
}, /*#__PURE__*/React__namespace.createElement(ColorSelect, {
|
|
31331
31941
|
selectedValue: color,
|
|
31332
31942
|
onChange: handleColorChange
|
|
@@ -31334,7 +31944,7 @@ const LockedPolygonSettings = props => {
|
|
|
31334
31944
|
size: wonderBlocksTokens.spacing.medium_16
|
|
31335
31945
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
31336
31946
|
tag: "label",
|
|
31337
|
-
style: [styles$
|
|
31947
|
+
style: [styles$k.row, styles$k.truncatedWidth]
|
|
31338
31948
|
}, "fill", /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
31339
31949
|
size: wonderBlocksTokens.spacing.xxSmall_6
|
|
31340
31950
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
@@ -31360,17 +31970,17 @@ const LockedPolygonSettings = props => {
|
|
|
31360
31970
|
onChange: newValue => onChangeProps({
|
|
31361
31971
|
showVertices: newValue
|
|
31362
31972
|
}),
|
|
31363
|
-
style: styles$
|
|
31973
|
+
style: styles$k.spaceUnder
|
|
31364
31974
|
}), /*#__PURE__*/React__namespace.createElement(PerseusEditorAccordion, {
|
|
31365
31975
|
header: /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, "Points"),
|
|
31366
31976
|
expanded: true,
|
|
31367
|
-
containerStyle: styles$
|
|
31368
|
-
panelStyle: styles$
|
|
31977
|
+
containerStyle: styles$k.pointAccordionContainer,
|
|
31978
|
+
panelStyle: styles$k.pointAccordionPanel
|
|
31369
31979
|
}, points.map((point, index) => {
|
|
31370
31980
|
const pointLabel = String.fromCharCode(65 + index);
|
|
31371
31981
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31372
31982
|
key: `locked-polygon-point-index-${index}`,
|
|
31373
|
-
style: [styles$
|
|
31983
|
+
style: [styles$k.row, styles$k.spaceUnder]
|
|
31374
31984
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, `${pointLabel}:`), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
31375
31985
|
size: wonderBlocksTokens.spacing.medium_16
|
|
31376
31986
|
}), /*#__PURE__*/React__namespace.createElement(CoordinatePairInput, {
|
|
@@ -31398,10 +32008,10 @@ const LockedPolygonSettings = props => {
|
|
|
31398
32008
|
points: newPoints
|
|
31399
32009
|
});
|
|
31400
32010
|
},
|
|
31401
|
-
style: styles$
|
|
32011
|
+
style: styles$k.icon
|
|
31402
32012
|
}));
|
|
31403
32013
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31404
|
-
style: [styles$
|
|
32014
|
+
style: [styles$k.row, styles$k.polygonActionsContainer]
|
|
31405
32015
|
}, /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
|
|
31406
32016
|
kind: "tertiary",
|
|
31407
32017
|
startIcon: plusCircle__default["default"],
|
|
@@ -31411,30 +32021,30 @@ const LockedPolygonSettings = props => {
|
|
|
31411
32021
|
});
|
|
31412
32022
|
}
|
|
31413
32023
|
}, "Add point"), /*#__PURE__*/React__namespace.createElement(Spring, null), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31414
|
-
style: styles$
|
|
32024
|
+
style: styles$k.movementButtonsContainer
|
|
31415
32025
|
}, /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
31416
32026
|
"aria-label": "Move polygon up",
|
|
31417
|
-
style: styles$
|
|
32027
|
+
style: styles$k.iconButton,
|
|
31418
32028
|
size: "small",
|
|
31419
32029
|
icon: arrowFatUp__default["default"],
|
|
31420
32030
|
onClick: () => handlePolygonMove("up")
|
|
31421
32031
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31422
|
-
style: styles$
|
|
32032
|
+
style: styles$k.row
|
|
31423
32033
|
}, /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
31424
32034
|
"aria-label": "Move polygon left",
|
|
31425
|
-
style: styles$
|
|
32035
|
+
style: styles$k.iconButton,
|
|
31426
32036
|
size: "small",
|
|
31427
32037
|
icon: arrowFatLeft__default["default"],
|
|
31428
32038
|
onClick: () => handlePolygonMove("left")
|
|
31429
32039
|
}), /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
31430
32040
|
"aria-label": "Move polygon down",
|
|
31431
|
-
style: styles$
|
|
32041
|
+
style: styles$k.iconButton,
|
|
31432
32042
|
size: "small",
|
|
31433
32043
|
icon: arrowFatDown__default["default"],
|
|
31434
32044
|
onClick: () => handlePolygonMove("down")
|
|
31435
32045
|
}), /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
31436
32046
|
"aria-label": "Move polygon right",
|
|
31437
|
-
style: styles$
|
|
32047
|
+
style: styles$k.iconButton,
|
|
31438
32048
|
size: "small",
|
|
31439
32049
|
icon: arrowFatRight__default["default"],
|
|
31440
32050
|
onClick: () => handlePolygonMove("right")
|
|
@@ -31444,7 +32054,7 @@ const LockedPolygonSettings = props => {
|
|
|
31444
32054
|
onRemove: onRemove
|
|
31445
32055
|
}));
|
|
31446
32056
|
};
|
|
31447
|
-
const styles$
|
|
32057
|
+
const styles$k = aphrodite.StyleSheet.create({
|
|
31448
32058
|
row: {
|
|
31449
32059
|
display: "flex",
|
|
31450
32060
|
flexDirection: "row",
|
|
@@ -31518,7 +32128,7 @@ const LockedVectorSettings = props => {
|
|
|
31518
32128
|
expanded: props.expanded,
|
|
31519
32129
|
onToggle: props.onToggle,
|
|
31520
32130
|
header: /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31521
|
-
style: styles$
|
|
32131
|
+
style: styles$j.row
|
|
31522
32132
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, lineLabel), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
31523
32133
|
size: wonderBlocksTokens.spacing.xSmall_8
|
|
31524
32134
|
}), /*#__PURE__*/React__namespace.createElement(LineSwatch, {
|
|
@@ -31526,19 +32136,19 @@ const LockedVectorSettings = props => {
|
|
|
31526
32136
|
lineStyle: "solid"
|
|
31527
32137
|
}))
|
|
31528
32138
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31529
|
-
style: [styles$
|
|
32139
|
+
style: [styles$j.row, styles$j.spaceUnder]
|
|
31530
32140
|
}, /*#__PURE__*/React__namespace.createElement(ColorSelect, {
|
|
31531
32141
|
selectedValue: lineColor,
|
|
31532
32142
|
onChange: handleColorChange
|
|
31533
32143
|
})), isInvalid && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
31534
|
-
style: styles$
|
|
32144
|
+
style: styles$j.errorText
|
|
31535
32145
|
}, lengthErrorMessage), /*#__PURE__*/React__namespace.createElement(PerseusEditorAccordion, {
|
|
31536
32146
|
expanded: true // Initial state is expanded
|
|
31537
32147
|
,
|
|
31538
|
-
containerStyle: styles$
|
|
31539
|
-
panelStyle: styles$
|
|
32148
|
+
containerStyle: styles$j.container,
|
|
32149
|
+
panelStyle: styles$j.accordionPanel,
|
|
31540
32150
|
header: /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31541
|
-
style: styles$
|
|
32151
|
+
style: styles$j.row
|
|
31542
32152
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, `Tail (${tail[0]}, ${tail[1]})`))
|
|
31543
32153
|
}, /*#__PURE__*/React__namespace.createElement(CoordinatePairInput, {
|
|
31544
32154
|
coord: tail,
|
|
@@ -31549,10 +32159,10 @@ const LockedVectorSettings = props => {
|
|
|
31549
32159
|
})), /*#__PURE__*/React__namespace.createElement(PerseusEditorAccordion, {
|
|
31550
32160
|
expanded: true // Initial state is expanded
|
|
31551
32161
|
,
|
|
31552
|
-
containerStyle: styles$
|
|
31553
|
-
panelStyle: styles$
|
|
32162
|
+
containerStyle: styles$j.container,
|
|
32163
|
+
panelStyle: styles$j.accordionPanel,
|
|
31554
32164
|
header: /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31555
|
-
style: styles$
|
|
32165
|
+
style: styles$j.row
|
|
31556
32166
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, null, `Tip (${tip[0]}, ${tip[1]})`))
|
|
31557
32167
|
}, /*#__PURE__*/React__namespace.createElement(CoordinatePairInput, {
|
|
31558
32168
|
coord: tip,
|
|
@@ -31566,7 +32176,7 @@ const LockedVectorSettings = props => {
|
|
|
31566
32176
|
onRemove: onRemove
|
|
31567
32177
|
}));
|
|
31568
32178
|
};
|
|
31569
|
-
const styles$
|
|
32179
|
+
const styles$j = aphrodite.StyleSheet.create({
|
|
31570
32180
|
accordionPanel: {
|
|
31571
32181
|
paddingBottom: wonderBlocksTokens.spacing.medium_16
|
|
31572
32182
|
},
|
|
@@ -31634,783 +32244,264 @@ const LockedFiguresSection = props => {
|
|
|
31634
32244
|
const lockedFigures = figures || [];
|
|
31635
32245
|
const newProps = {
|
|
31636
32246
|
lockedFigures: [...lockedFigures, getDefaultFigureForType(newFigure)]
|
|
31637
|
-
};
|
|
31638
|
-
onChange(newProps);
|
|
31639
|
-
setExpandedStates([...expandedStates, true]);
|
|
31640
|
-
}
|
|
31641
|
-
function moveLockedFigure(index, movement) {
|
|
31642
|
-
// Don't allow moving the first figure up or the last figure down.
|
|
31643
|
-
if (index === 0 && (movement === "back" || movement === "backward")) {
|
|
31644
|
-
return;
|
|
31645
|
-
}
|
|
31646
|
-
if (figures && index === figures.length - 1 && (movement === "front" || movement === "forward")) {
|
|
31647
|
-
return;
|
|
31648
|
-
}
|
|
31649
|
-
const lockedFigures = figures || [];
|
|
31650
|
-
const newFigures = [...lockedFigures];
|
|
31651
|
-
const newExpandedStates = [...expandedStates];
|
|
31652
|
-
|
|
31653
|
-
// First, remove the figure from its current position
|
|
31654
|
-
// in the figures array and the expanded states array.
|
|
31655
|
-
const [removedFigure] = newFigures.splice(index, 1);
|
|
31656
|
-
newExpandedStates.splice(index, 1);
|
|
31657
|
-
|
|
31658
|
-
// Then, add it back in the new position. Add "true" to the
|
|
31659
|
-
// expanded states array for the new position (it must already
|
|
31660
|
-
// be open since the button to move it is being pressed from there).
|
|
31661
|
-
switch (movement) {
|
|
31662
|
-
case "back":
|
|
31663
|
-
newFigures.unshift(removedFigure);
|
|
31664
|
-
newExpandedStates.unshift(true);
|
|
31665
|
-
break;
|
|
31666
|
-
case "backward":
|
|
31667
|
-
newFigures.splice(index - 1, 0, removedFigure);
|
|
31668
|
-
newExpandedStates.splice(index - 1, 0, true);
|
|
31669
|
-
break;
|
|
31670
|
-
case "forward":
|
|
31671
|
-
newFigures.splice(index + 1, 0, removedFigure);
|
|
31672
|
-
newExpandedStates.splice(index + 1, 0, true);
|
|
31673
|
-
break;
|
|
31674
|
-
case "front":
|
|
31675
|
-
newFigures.push(removedFigure);
|
|
31676
|
-
newExpandedStates.push(true);
|
|
31677
|
-
break;
|
|
31678
|
-
}
|
|
31679
|
-
onChange({
|
|
31680
|
-
lockedFigures: newFigures
|
|
31681
|
-
});
|
|
31682
|
-
setExpandedStates(newExpandedStates);
|
|
31683
|
-
}
|
|
31684
|
-
function removeLockedFigure(index) {
|
|
31685
|
-
// eslint-disable-next-line no-alert
|
|
31686
|
-
if (window.confirm("Are you sure you want to delete this figure?")) {
|
|
31687
|
-
const lockedFigures = figures || [];
|
|
31688
|
-
onChange({
|
|
31689
|
-
lockedFigures: [...lockedFigures.slice(0, index), ...lockedFigures.slice(index + 1)]
|
|
31690
|
-
});
|
|
31691
|
-
|
|
31692
|
-
// Update expanded states
|
|
31693
|
-
const newExpandedStates = [...expandedStates];
|
|
31694
|
-
newExpandedStates.splice(index, 1);
|
|
31695
|
-
setExpandedStates(newExpandedStates);
|
|
31696
|
-
}
|
|
31697
|
-
}
|
|
31698
|
-
function changeProps(index,
|
|
31699
|
-
// Omit the type from the figure props so it doesn't think
|
|
31700
|
-
// we're trying to pass in the props for the wrong type.
|
|
31701
|
-
figureProps) {
|
|
31702
|
-
const lockedFigures = figures || [];
|
|
31703
|
-
const newFigures = {
|
|
31704
|
-
lockedFigures: [...lockedFigures.slice(0, index), {
|
|
31705
|
-
...lockedFigures[index],
|
|
31706
|
-
...figureProps
|
|
31707
|
-
}, ...lockedFigures.slice(index + 1)]
|
|
31708
|
-
};
|
|
31709
|
-
onChange(newFigures);
|
|
31710
|
-
}
|
|
31711
|
-
function toggleExpanded(newValue) {
|
|
31712
|
-
setExpandedStates(Array(figures?.length).fill(newValue));
|
|
31713
|
-
}
|
|
31714
|
-
const allCollapsed = expandedStates.every(value => !value);
|
|
31715
|
-
const buttonLabel = allCollapsed ? "Expand all" : "Collapse all";
|
|
31716
|
-
const showExpandButton = !!figures?.length;
|
|
31717
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Heading, {
|
|
31718
|
-
title: "Locked Figures",
|
|
31719
|
-
isOpen: isExpanded,
|
|
31720
|
-
onToggle: () => setIsExpanded(!isExpanded),
|
|
31721
|
-
isCollapsible: true
|
|
31722
|
-
}), isExpanded && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, figures?.map((figure, index) => {
|
|
31723
|
-
return /*#__PURE__*/React__namespace.createElement(LockedFigureSettings, _extends({
|
|
31724
|
-
key: `${uniqueId}-locked-${figure}-${index}`,
|
|
31725
|
-
showLabelsFlag: props.showLabelsFlag,
|
|
31726
|
-
expanded: expandedStates[index],
|
|
31727
|
-
onToggle: newValue => {
|
|
31728
|
-
const newExpanded = [...expandedStates];
|
|
31729
|
-
newExpanded[index] = newValue;
|
|
31730
|
-
setExpandedStates(newExpanded);
|
|
31731
|
-
}
|
|
31732
|
-
}, figure, {
|
|
31733
|
-
onChangeProps: newProps => changeProps(index, newProps),
|
|
31734
|
-
onMove: movement => moveLockedFigure(index, movement),
|
|
31735
|
-
onRemove: () => removeLockedFigure(index)
|
|
31736
|
-
}));
|
|
31737
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31738
|
-
style: styles$n.buttonContainer
|
|
31739
|
-
}, /*#__PURE__*/React__namespace.createElement(LockedFigureSelect, {
|
|
31740
|
-
showLabelsFlag: props.showLabelsFlag,
|
|
31741
|
-
id: `${uniqueId}-select`,
|
|
31742
|
-
onChange: addLockedFigure
|
|
31743
|
-
}), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
31744
|
-
size: wonderBlocksTokens.spacing.small_12
|
|
31745
|
-
}), showExpandButton && /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
|
|
31746
|
-
kind: "secondary",
|
|
31747
|
-
onClick: () => toggleExpanded(allCollapsed),
|
|
31748
|
-
style: styles$n.button
|
|
31749
|
-
}, buttonLabel))));
|
|
31750
|
-
};
|
|
31751
|
-
const styles$n = aphrodite.StyleSheet.create({
|
|
31752
|
-
buttonContainer: {
|
|
31753
|
-
flexDirection: "row",
|
|
31754
|
-
alignItems: "center"
|
|
31755
|
-
},
|
|
31756
|
-
button: {
|
|
31757
|
-
marginTop: wonderBlocksTokens.spacing.xSmall_8,
|
|
31758
|
-
flexGrow: 1
|
|
31759
|
-
}
|
|
31760
|
-
});
|
|
31761
|
-
|
|
31762
|
-
const UNLIMITED = "unlimited";
|
|
31763
|
-
// Parses a string (ostensibly from some UI element that only supports string
|
|
31764
|
-
// types, such as a <select />) into a numeric point count or the special sigil
|
|
31765
|
-
// "unlimited". Note that 0 is a special case, and means "unlimited".
|
|
31766
|
-
const parsePointCount = points => {
|
|
31767
|
-
const parsed = parseInt(points, 10);
|
|
31768
|
-
if (isNaN(parsed)) {
|
|
31769
|
-
return UNLIMITED;
|
|
31770
|
-
}
|
|
31771
|
-
return parsed === 0 ? UNLIMITED : parsed;
|
|
31772
|
-
};
|
|
31773
|
-
|
|
31774
|
-
const GraphPointsCountSelector = _ref => {
|
|
31775
|
-
let {
|
|
31776
|
-
numPoints = 1,
|
|
31777
|
-
onChange
|
|
31778
|
-
} = _ref;
|
|
31779
|
-
return /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
31780
|
-
selectedValue: `${numPoints}`,
|
|
31781
|
-
onChange: newValue => {
|
|
31782
|
-
onChange(parsePointCount(newValue));
|
|
31783
|
-
}
|
|
31784
|
-
// Never uses placeholder, always has value
|
|
31785
|
-
,
|
|
31786
|
-
placeholder: "",
|
|
31787
|
-
style: styles$m.singleSelectShort
|
|
31788
|
-
}, [...[...Array(7).keys()].map(n => /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31789
|
-
key: n,
|
|
31790
|
-
value: `${n}`,
|
|
31791
|
-
label: `${n} point${n > 1 ? "s" : ""}`
|
|
31792
|
-
})), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31793
|
-
key: "unlimited",
|
|
31794
|
-
value: UNLIMITED,
|
|
31795
|
-
label: "unlimited"
|
|
31796
|
-
})]);
|
|
31797
|
-
};
|
|
31798
|
-
const styles$m = aphrodite.StyleSheet.create({
|
|
31799
|
-
singleSelectShort: {
|
|
31800
|
-
// Non-standard spacing, but it's the smallest we can go
|
|
31801
|
-
// without running into styling issues with the dropdown.
|
|
31802
|
-
height: 26
|
|
31803
|
-
}
|
|
31804
|
-
});
|
|
31805
|
-
|
|
31806
|
-
const GraphTypeSelector = props => {
|
|
31807
|
-
return /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
31808
|
-
selectedValue: props.graphType,
|
|
31809
|
-
onChange: props.onChange,
|
|
31810
|
-
placeholder: "Select a graph type",
|
|
31811
|
-
style: styles$l.singleSelectShort
|
|
31812
|
-
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31813
|
-
value: "linear",
|
|
31814
|
-
label: "Linear function"
|
|
31815
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31816
|
-
value: "quadratic",
|
|
31817
|
-
label: "Quadratic function"
|
|
31818
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31819
|
-
value: "sinusoid",
|
|
31820
|
-
label: "Sinusoid function"
|
|
31821
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31822
|
-
value: "circle",
|
|
31823
|
-
label: "Circle"
|
|
31824
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31825
|
-
value: "point",
|
|
31826
|
-
label: "Point(s)"
|
|
31827
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31828
|
-
value: "linear-system",
|
|
31829
|
-
label: "Linear System"
|
|
31830
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31831
|
-
value: "polygon",
|
|
31832
|
-
label: "Polygon"
|
|
31833
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31834
|
-
value: "segment",
|
|
31835
|
-
label: "Line Segment(s)"
|
|
31836
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31837
|
-
value: "ray",
|
|
31838
|
-
label: "Ray"
|
|
31839
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31840
|
-
value: "angle",
|
|
31841
|
-
label: "Angle"
|
|
31842
|
-
}));
|
|
31843
|
-
};
|
|
31844
|
-
const styles$l = aphrodite.StyleSheet.create({
|
|
31845
|
-
singleSelectShort: {
|
|
31846
|
-
// Non-standard spacing, but it's the smallest we can go
|
|
31847
|
-
// without running into styling issues with the dropdown.
|
|
31848
|
-
height: 26
|
|
31849
|
-
}
|
|
31850
|
-
});
|
|
31851
|
-
|
|
31852
|
-
function InteractiveGraphCorrectAnswer(props) {
|
|
31853
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Heading, {
|
|
31854
|
-
title: "Correct Answer",
|
|
31855
|
-
isOpen: true,
|
|
31856
|
-
isCollapsible: false
|
|
31857
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelXSmall, {
|
|
31858
|
-
style: {
|
|
31859
|
-
paddingTop: wonderBlocksTokens.spacing.xxSmall_6,
|
|
31860
|
-
paddingBottom: wonderBlocksTokens.spacing.xxSmall_6,
|
|
31861
|
-
color: wonderBlocksTokens.color.offBlack64
|
|
31862
|
-
}
|
|
31863
|
-
}, "Graph the correct answer in the graph below and ensure the equation or point coordinates displayed represent the correct answer."), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.BodyMonospace, {
|
|
31864
|
-
style: {
|
|
31865
|
-
fontSize: 12,
|
|
31866
|
-
backgroundColor: "#eee",
|
|
31867
|
-
paddingInline: wonderBlocksTokens.spacing.xxSmall_6,
|
|
31868
|
-
borderColor: "#ccc",
|
|
31869
|
-
borderStyle: "solid",
|
|
31870
|
-
borderWidth: 1
|
|
31871
|
-
}
|
|
31872
|
-
}, props.equationString)), props.children));
|
|
31873
|
-
}
|
|
31874
|
-
|
|
31875
|
-
function InteractiveGraphDescription(props) {
|
|
31876
|
-
const {
|
|
31877
|
-
ariaLabelValue,
|
|
31878
|
-
ariaDescriptionValue,
|
|
31879
|
-
onChange
|
|
31880
|
-
} = props;
|
|
31881
|
-
const [isOpen, setIsOpen] = React__namespace.useState(true);
|
|
31882
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Heading, {
|
|
31883
|
-
title: "Description",
|
|
31884
|
-
isCollapsible: true,
|
|
31885
|
-
isOpen: isOpen,
|
|
31886
|
-
onToggle: setIsOpen
|
|
31887
|
-
}), isOpen && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelXSmall, {
|
|
31888
|
-
style: styles$k.caption
|
|
31889
|
-
}, "Use these fields to describe the graph as a whole. These are used by screen readers to describe content to users who are visually impaired."), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, {
|
|
31890
|
-
tag: "label"
|
|
31891
|
-
}, "Title", /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextField, {
|
|
31892
|
-
value: ariaLabelValue,
|
|
31893
|
-
onChange: newValue => onChange({
|
|
31894
|
-
fullGraphAriaLabel: newValue
|
|
31895
|
-
}),
|
|
31896
|
-
style: styles$k.spaceAbove
|
|
31897
|
-
})), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
31898
|
-
size: wonderBlocksTokens.spacing.small_12
|
|
31899
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelLarge, {
|
|
31900
|
-
tag: "label"
|
|
31901
|
-
}, "Description", /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.TextArea, {
|
|
31902
|
-
rows: 8,
|
|
31903
|
-
resizeType: "vertical",
|
|
31904
|
-
value: ariaDescriptionValue,
|
|
31905
|
-
onChange: newValue => onChange({
|
|
31906
|
-
fullGraphAriaDescription: newValue
|
|
31907
|
-
}),
|
|
31908
|
-
style: styles$k.spaceAbove
|
|
31909
|
-
}))));
|
|
31910
|
-
}
|
|
31911
|
-
const styles$k = aphrodite.StyleSheet.create({
|
|
31912
|
-
caption: {
|
|
31913
|
-
color: wonderBlocksTokens.color.offBlack64,
|
|
31914
|
-
paddingTop: wonderBlocksTokens.spacing.xxSmall_6,
|
|
31915
|
-
paddingBottom: wonderBlocksTokens.spacing.xxSmall_6
|
|
31916
|
-
},
|
|
31917
|
-
spaceAbove: {
|
|
31918
|
-
marginTop: wonderBlocksTokens.spacing.xxxSmall_4
|
|
31919
|
-
}
|
|
31920
|
-
});
|
|
31921
|
-
|
|
31922
|
-
/* eslint-disable react/forbid-prop-types, react/no-unsafe */
|
|
31923
|
-
const {
|
|
31924
|
-
ButtonGroup: ButtonGroup$2,
|
|
31925
|
-
InfoTip: InfoTip$c,
|
|
31926
|
-
RangeInput: RangeInput$4
|
|
31927
|
-
} = perseus.components;
|
|
31928
|
-
const defaultBackgroundImage$1 = {
|
|
31929
|
-
url: null,
|
|
31930
|
-
width: 0,
|
|
31931
|
-
height: 0
|
|
31932
|
-
};
|
|
31933
|
-
function numSteps(range, step) {
|
|
31934
|
-
return Math.floor((range[1] - range[0]) / step);
|
|
31935
|
-
}
|
|
31936
|
-
class InteractiveGraphSettings extends React__namespace.Component {
|
|
31937
|
-
_isMounted = false;
|
|
31938
|
-
bgUrlRef = /*#__PURE__*/React__namespace.createRef();
|
|
31939
|
-
labelXRef = /*#__PURE__*/React__namespace.createRef();
|
|
31940
|
-
labelYRef = /*#__PURE__*/React__namespace.createRef();
|
|
31941
|
-
static stateFromProps(props) {
|
|
31942
|
-
return {
|
|
31943
|
-
labelsTextbox: props.labels,
|
|
31944
|
-
gridStepTextbox: props.gridStep,
|
|
31945
|
-
snapStepTextbox: props.snapStep,
|
|
31946
|
-
stepTextbox: props.step,
|
|
31947
|
-
rangeTextbox: props.range,
|
|
31948
|
-
// Shallow-copied clone
|
|
31949
|
-
backgroundImage: {
|
|
31950
|
-
...props.backgroundImage
|
|
31951
|
-
}
|
|
31952
|
-
};
|
|
31953
|
-
}
|
|
31954
|
-
constructor(props) {
|
|
31955
|
-
super(props);
|
|
31956
|
-
this.state = {
|
|
31957
|
-
isExpanded: true,
|
|
31958
|
-
...InteractiveGraphSettings.stateFromProps(props)
|
|
31959
|
-
};
|
|
31960
|
-
}
|
|
31961
|
-
static defaultProps = {
|
|
31962
|
-
box: [perseus.interactiveSizes.defaultBoxSizeSmall, perseus.interactiveSizes.defaultBoxSizeSmall],
|
|
31963
|
-
labels: ["x", "y"],
|
|
31964
|
-
range: [[-10, 10], [-10, 10]],
|
|
31965
|
-
step: [1, 1],
|
|
31966
|
-
gridStep: [1, 1],
|
|
31967
|
-
snapStep: [1, 1],
|
|
31968
|
-
valid: true,
|
|
31969
|
-
backgroundImage: defaultBackgroundImage$1,
|
|
31970
|
-
markings: "graph",
|
|
31971
|
-
showProtractor: false,
|
|
31972
|
-
showTooltips: false
|
|
31973
|
-
};
|
|
31974
|
-
componentDidMount() {
|
|
31975
|
-
// TODO(scottgrant): This is a hack to remove the deprecated call to
|
|
31976
|
-
// this.isMounted() but is still considered an anti-pattern.
|
|
31977
|
-
this._isMounted = true;
|
|
31978
|
-
this.changeGraph = ___default["default"].debounce(this.changeGraph, 300);
|
|
31979
|
-
}
|
|
31980
|
-
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
31981
|
-
// Make sure that state updates when switching
|
|
31982
|
-
// between different items in a multi-item editor.
|
|
31983
|
-
if (!___default["default"].isEqual(this.props.labels, nextProps.labels) || !___default["default"].isEqual(this.props.gridStep, nextProps.gridStep) || !___default["default"].isEqual(this.props.snapStep, nextProps.snapStep) || !___default["default"].isEqual(this.props.step, nextProps.step) || !___default["default"].isEqual(this.props.range, nextProps.range) || !___default["default"].isEqual(this.props.backgroundImage, nextProps.backgroundImage)) {
|
|
31984
|
-
this.setState(InteractiveGraphSettings.stateFromProps(nextProps));
|
|
31985
|
-
}
|
|
31986
|
-
}
|
|
31987
|
-
componentWillUnmount() {
|
|
31988
|
-
this._isMounted = false;
|
|
31989
|
-
}
|
|
31990
|
-
change = (() => {
|
|
31991
|
-
var _this = this;
|
|
31992
|
-
return function () {
|
|
31993
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
31994
|
-
args[_key] = arguments[_key];
|
|
31995
|
-
}
|
|
31996
|
-
return perseus.Changeable.change.apply(_this, args);
|
|
31997
|
-
};
|
|
31998
|
-
})();
|
|
31999
|
-
changeBackgroundUrl = e => {
|
|
32000
|
-
// Only continue on blur or "enter"
|
|
32001
|
-
if (e.type === "keypress" && e.key !== "Enter") {
|
|
32002
|
-
return;
|
|
32003
|
-
}
|
|
32004
|
-
const setUrl = (url, width, height) => {
|
|
32005
|
-
// Shallow-copied clone
|
|
32006
|
-
const image = {
|
|
32007
|
-
...this.props.backgroundImage
|
|
32008
|
-
};
|
|
32009
|
-
image.url = url;
|
|
32010
|
-
image.width = width;
|
|
32011
|
-
image.height = height;
|
|
32012
|
-
this.setState({
|
|
32013
|
-
backgroundImage: image
|
|
32014
|
-
}, this.changeGraph);
|
|
32015
|
-
};
|
|
32016
|
-
const url = this.bgUrlRef.current?.value;
|
|
32017
|
-
if (url) {
|
|
32018
|
-
perseus.Util.getImageSize(url, (width, height) => {
|
|
32019
|
-
if (this._isMounted) {
|
|
32020
|
-
setUrl(url, width, height);
|
|
32021
|
-
}
|
|
32022
|
-
});
|
|
32023
|
-
} else {
|
|
32024
|
-
setUrl(null, 0, 0);
|
|
32025
|
-
}
|
|
32026
|
-
};
|
|
32027
|
-
renderLabelChoices = choices => {
|
|
32028
|
-
return choices.map(nameAndValue => /*#__PURE__*/React__namespace.createElement("option", {
|
|
32029
|
-
key: nameAndValue[1],
|
|
32030
|
-
value: nameAndValue[1]
|
|
32031
|
-
}, nameAndValue[0]));
|
|
32032
|
-
};
|
|
32033
|
-
validRange = range => {
|
|
32034
|
-
const numbers = ___default["default"].every(range, function (num) {
|
|
32035
|
-
return ___default["default"].isFinite(num);
|
|
32036
|
-
});
|
|
32037
|
-
if (!numbers) {
|
|
32038
|
-
return "Range must be a valid number";
|
|
32039
|
-
}
|
|
32040
|
-
if (range[0] >= range[1]) {
|
|
32041
|
-
return "Range must have a higher number on the right";
|
|
32042
|
-
}
|
|
32043
|
-
return true;
|
|
32044
|
-
};
|
|
32045
|
-
validateStepValue = settings => {
|
|
32046
|
-
const {
|
|
32047
|
-
step,
|
|
32048
|
-
range,
|
|
32049
|
-
name,
|
|
32050
|
-
minTicks,
|
|
32051
|
-
maxTicks
|
|
32052
|
-
} = settings;
|
|
32053
|
-
const nSteps = numSteps(range, step);
|
|
32054
|
-
if (nSteps < minTicks) {
|
|
32055
|
-
return name + " is too large, there must be at least " + minTicks + " ticks.";
|
|
32056
|
-
}
|
|
32057
|
-
if (nSteps > maxTicks) {
|
|
32058
|
-
return name + " is too small, there can be at most " + maxTicks + " ticks.";
|
|
32059
|
-
}
|
|
32060
|
-
return true;
|
|
32061
|
-
};
|
|
32062
|
-
validSnapStep = (step, range) => {
|
|
32063
|
-
return this.validateStepValue({
|
|
32064
|
-
step: step,
|
|
32065
|
-
range: range,
|
|
32066
|
-
name: "Snap step",
|
|
32067
|
-
minTicks: 5,
|
|
32068
|
-
maxTicks: 60
|
|
32069
|
-
});
|
|
32070
|
-
};
|
|
32071
|
-
validGridStep = (step, range) => {
|
|
32072
|
-
return this.validateStepValue({
|
|
32073
|
-
step: step,
|
|
32074
|
-
range: range,
|
|
32075
|
-
name: "Grid step",
|
|
32076
|
-
minTicks: 3,
|
|
32077
|
-
maxTicks: 60
|
|
32078
|
-
});
|
|
32079
|
-
};
|
|
32080
|
-
validStep = (step, range) => {
|
|
32081
|
-
return this.validateStepValue({
|
|
32082
|
-
step: step,
|
|
32083
|
-
range: range,
|
|
32084
|
-
name: "Step",
|
|
32085
|
-
minTicks: 3,
|
|
32086
|
-
maxTicks: 20
|
|
32087
|
-
});
|
|
32088
|
-
};
|
|
32089
|
-
validBackgroundImageSize = image => {
|
|
32090
|
-
// Ignore empty images
|
|
32091
|
-
if (!image.url) {
|
|
32092
|
-
return true;
|
|
32093
|
-
}
|
|
32094
|
-
const validSize = image.width <= 450 && image.height <= 450;
|
|
32095
|
-
if (!validSize) {
|
|
32096
|
-
return "Image must be smaller than 450px x 450px.";
|
|
32097
|
-
}
|
|
32098
|
-
return true;
|
|
32099
|
-
};
|
|
32100
|
-
validateGraphSettings = (range, step, gridStep, snapStep, image) => {
|
|
32101
|
-
const self = this;
|
|
32102
|
-
let msg;
|
|
32103
|
-
const goodRange = ___default["default"].every(range, function (range) {
|
|
32104
|
-
msg = self.validRange(range);
|
|
32105
|
-
return msg === true;
|
|
32106
|
-
});
|
|
32107
|
-
if (!goodRange) {
|
|
32108
|
-
return msg;
|
|
32109
|
-
}
|
|
32110
|
-
const goodStep = ___default["default"].every(step, function (step, i) {
|
|
32111
|
-
msg = self.validStep(step, range[i]);
|
|
32112
|
-
return msg === true;
|
|
32113
|
-
});
|
|
32114
|
-
if (!goodStep) {
|
|
32115
|
-
return msg;
|
|
32116
|
-
}
|
|
32117
|
-
const goodGridStep = ___default["default"].every(gridStep, function (gridStep, i) {
|
|
32118
|
-
msg = self.validGridStep(gridStep, range[i]);
|
|
32119
|
-
return msg === true;
|
|
32120
|
-
});
|
|
32121
|
-
if (!goodGridStep) {
|
|
32122
|
-
return msg;
|
|
32123
|
-
}
|
|
32124
|
-
const goodSnapStep = ___default["default"].every(snapStep, function (snapStep, i) {
|
|
32125
|
-
msg = self.validSnapStep(snapStep, range[i]);
|
|
32126
|
-
return msg === true;
|
|
32127
|
-
});
|
|
32128
|
-
if (!goodSnapStep) {
|
|
32129
|
-
return msg;
|
|
32247
|
+
};
|
|
32248
|
+
onChange(newProps);
|
|
32249
|
+
setExpandedStates([...expandedStates, true]);
|
|
32250
|
+
}
|
|
32251
|
+
function moveLockedFigure(index, movement) {
|
|
32252
|
+
// Don't allow moving the first figure up or the last figure down.
|
|
32253
|
+
if (index === 0 && (movement === "back" || movement === "backward")) {
|
|
32254
|
+
return;
|
|
32130
32255
|
}
|
|
32131
|
-
|
|
32132
|
-
|
|
32133
|
-
msg = goodImageSize;
|
|
32134
|
-
return msg;
|
|
32256
|
+
if (figures && index === figures.length - 1 && (movement === "front" || movement === "forward")) {
|
|
32257
|
+
return;
|
|
32135
32258
|
}
|
|
32136
|
-
|
|
32137
|
-
|
|
32138
|
-
|
|
32139
|
-
|
|
32140
|
-
|
|
32141
|
-
|
|
32142
|
-
|
|
32143
|
-
|
|
32144
|
-
|
|
32145
|
-
|
|
32146
|
-
|
|
32147
|
-
|
|
32148
|
-
|
|
32149
|
-
|
|
32150
|
-
|
|
32151
|
-
|
|
32152
|
-
|
|
32153
|
-
|
|
32154
|
-
|
|
32155
|
-
|
|
32156
|
-
|
|
32157
|
-
|
|
32158
|
-
|
|
32159
|
-
|
|
32259
|
+
const lockedFigures = figures || [];
|
|
32260
|
+
const newFigures = [...lockedFigures];
|
|
32261
|
+
const newExpandedStates = [...expandedStates];
|
|
32262
|
+
|
|
32263
|
+
// First, remove the figure from its current position
|
|
32264
|
+
// in the figures array and the expanded states array.
|
|
32265
|
+
const [removedFigure] = newFigures.splice(index, 1);
|
|
32266
|
+
newExpandedStates.splice(index, 1);
|
|
32267
|
+
|
|
32268
|
+
// Then, add it back in the new position. Add "true" to the
|
|
32269
|
+
// expanded states array for the new position (it must already
|
|
32270
|
+
// be open since the button to move it is being pressed from there).
|
|
32271
|
+
switch (movement) {
|
|
32272
|
+
case "back":
|
|
32273
|
+
newFigures.unshift(removedFigure);
|
|
32274
|
+
newExpandedStates.unshift(true);
|
|
32275
|
+
break;
|
|
32276
|
+
case "backward":
|
|
32277
|
+
newFigures.splice(index - 1, 0, removedFigure);
|
|
32278
|
+
newExpandedStates.splice(index - 1, 0, true);
|
|
32279
|
+
break;
|
|
32280
|
+
case "forward":
|
|
32281
|
+
newFigures.splice(index + 1, 0, removedFigure);
|
|
32282
|
+
newExpandedStates.splice(index + 1, 0, true);
|
|
32283
|
+
break;
|
|
32284
|
+
case "front":
|
|
32285
|
+
newFigures.push(removedFigure);
|
|
32286
|
+
newExpandedStates.push(true);
|
|
32287
|
+
break;
|
|
32160
32288
|
}
|
|
32161
|
-
|
|
32162
|
-
|
|
32163
|
-
gridStepTextbox: gridStep,
|
|
32164
|
-
snapStepTextbox: snapStep,
|
|
32165
|
-
rangeTextbox: ranges
|
|
32166
|
-
}, this.changeGraph);
|
|
32167
|
-
};
|
|
32168
|
-
changeStep = step => {
|
|
32169
|
-
this.setState({
|
|
32170
|
-
stepTextbox: step
|
|
32171
|
-
}, this.changeGraph);
|
|
32172
|
-
};
|
|
32173
|
-
changeSnapStep = snapStep => {
|
|
32174
|
-
this.setState({
|
|
32175
|
-
snapStepTextbox: snapStep
|
|
32176
|
-
}, this.changeGraph);
|
|
32177
|
-
};
|
|
32178
|
-
changeGridStep = gridStep => {
|
|
32179
|
-
this.setState({
|
|
32180
|
-
gridStepTextbox: gridStep,
|
|
32181
|
-
snapStepTextbox: ___default["default"].map(gridStep, function (step) {
|
|
32182
|
-
return step / 2;
|
|
32183
|
-
})
|
|
32184
|
-
}, this.changeGraph);
|
|
32185
|
-
};
|
|
32186
|
-
changeGraph = () => {
|
|
32187
|
-
const labels = this.state.labelsTextbox;
|
|
32188
|
-
const range = ___default["default"].map(this.state.rangeTextbox, function (range) {
|
|
32189
|
-
return ___default["default"].map(range, Number);
|
|
32289
|
+
onChange({
|
|
32290
|
+
lockedFigures: newFigures
|
|
32190
32291
|
});
|
|
32191
|
-
|
|
32192
|
-
|
|
32193
|
-
|
|
32194
|
-
|
|
32195
|
-
|
|
32196
|
-
|
|
32197
|
-
|
|
32198
|
-
|
|
32199
|
-
// is contained in the string
|
|
32200
|
-
// TODO(aria): Refactor this to not be confusing
|
|
32201
|
-
const validationResult = this.validateGraphSettings(range, step, gridStep, snapStep, image);
|
|
32202
|
-
if (validationResult === true) {
|
|
32203
|
-
// either true or a string
|
|
32204
|
-
this.change({
|
|
32205
|
-
valid: true,
|
|
32206
|
-
labels: labels,
|
|
32207
|
-
range: range,
|
|
32208
|
-
step: step,
|
|
32209
|
-
gridStep: gridStep,
|
|
32210
|
-
snapStep: snapStep,
|
|
32211
|
-
backgroundImage: image
|
|
32212
|
-
});
|
|
32213
|
-
} else {
|
|
32214
|
-
this.change({
|
|
32215
|
-
valid: validationResult // a string message, not false
|
|
32292
|
+
setExpandedStates(newExpandedStates);
|
|
32293
|
+
}
|
|
32294
|
+
function removeLockedFigure(index) {
|
|
32295
|
+
// eslint-disable-next-line no-alert
|
|
32296
|
+
if (window.confirm("Are you sure you want to delete this figure?")) {
|
|
32297
|
+
const lockedFigures = figures || [];
|
|
32298
|
+
onChange({
|
|
32299
|
+
lockedFigures: [...lockedFigures.slice(0, index), ...lockedFigures.slice(index + 1)]
|
|
32216
32300
|
});
|
|
32217
|
-
}
|
|
32218
|
-
};
|
|
32219
32301
|
|
|
32220
|
-
|
|
32221
|
-
|
|
32222
|
-
|
|
32223
|
-
|
|
32224
|
-
|
|
32225
|
-
onToggle: () => this.setState({
|
|
32226
|
-
isExpanded: !this.state.isExpanded
|
|
32227
|
-
})
|
|
32228
|
-
}), this.state.isExpanded && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement("div", {
|
|
32229
|
-
className: "graph-settings"
|
|
32230
|
-
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
32231
|
-
className: "perseus-widget-row"
|
|
32232
|
-
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
32233
|
-
className: "perseus-widget-left-col"
|
|
32234
|
-
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
32235
|
-
label: "x Label"
|
|
32236
|
-
}, /*#__PURE__*/React__namespace.createElement("input", {
|
|
32237
|
-
type: "text",
|
|
32238
|
-
className: "graph-settings-axis-label",
|
|
32239
|
-
ref: this.labelXRef,
|
|
32240
|
-
onChange: e => this.changeLabel(0, e),
|
|
32241
|
-
value: this.state.labelsTextbox[0] || ""
|
|
32242
|
-
}))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
32243
|
-
className: "perseus-widget-right-col"
|
|
32244
|
-
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
32245
|
-
label: "y Label"
|
|
32246
|
-
}, /*#__PURE__*/React__namespace.createElement("input", {
|
|
32247
|
-
type: "text",
|
|
32248
|
-
className: "graph-settings-axis-label",
|
|
32249
|
-
ref: this.labelYRef,
|
|
32250
|
-
onChange: e => this.changeLabel(1, e),
|
|
32251
|
-
value: this.state.labelsTextbox[1] || ""
|
|
32252
|
-
})))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
32253
|
-
className: "perseus-widget-row"
|
|
32254
|
-
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
32255
|
-
className: "perseus-widget-left-col"
|
|
32256
|
-
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
32257
|
-
label: "x Range"
|
|
32258
|
-
}, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
|
|
32259
|
-
value: this.state.rangeTextbox[0],
|
|
32260
|
-
onChange: vals => this.changeRange(0, vals)
|
|
32261
|
-
}))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
32262
|
-
className: "perseus-widget-right-col"
|
|
32263
|
-
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
32264
|
-
label: "y Range"
|
|
32265
|
-
}, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
|
|
32266
|
-
value: this.state.rangeTextbox[1],
|
|
32267
|
-
onChange: vals => this.changeRange(1, vals)
|
|
32268
|
-
})))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
32269
|
-
className: "perseus-widget-row"
|
|
32270
|
-
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
32271
|
-
className: "perseus-widget-left-col"
|
|
32272
|
-
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
32273
|
-
label: "Tick Step"
|
|
32274
|
-
}, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
|
|
32275
|
-
value: this.state.stepTextbox,
|
|
32276
|
-
onChange: this.changeStep
|
|
32277
|
-
}))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
32278
|
-
className: "perseus-widget-right-col"
|
|
32279
|
-
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
32280
|
-
label: "Grid Step"
|
|
32281
|
-
}, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
|
|
32282
|
-
value: this.state.gridStepTextbox,
|
|
32283
|
-
onChange: this.changeGridStep
|
|
32284
|
-
})))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
32285
|
-
className: "perseus-widget-row"
|
|
32286
|
-
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
32287
|
-
className: "perseus-widget-left-col"
|
|
32288
|
-
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
32289
|
-
label: "Snap Step"
|
|
32290
|
-
}, /*#__PURE__*/React__namespace.createElement(RangeInput$4, {
|
|
32291
|
-
value: this.state.snapStepTextbox,
|
|
32292
|
-
onChange: this.changeSnapStep
|
|
32293
|
-
})))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
32294
|
-
className: "perseus-widget-row"
|
|
32295
|
-
}, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
32296
|
-
label: "Markings:"
|
|
32297
|
-
}, /*#__PURE__*/React__namespace.createElement(ButtonGroup$2, {
|
|
32298
|
-
value: this.props.markings,
|
|
32299
|
-
allowEmpty: false,
|
|
32300
|
-
buttons: [{
|
|
32301
|
-
value: "graph",
|
|
32302
|
-
content: "Graph"
|
|
32303
|
-
}, {
|
|
32304
|
-
value: "grid",
|
|
32305
|
-
content: "Grid"
|
|
32306
|
-
}, {
|
|
32307
|
-
value: "none",
|
|
32308
|
-
content: "None"
|
|
32309
|
-
}],
|
|
32310
|
-
onChange: this.change("markings")
|
|
32311
|
-
}))), /*#__PURE__*/React__namespace.createElement("div", {
|
|
32312
|
-
className: "perseus-widget-left-col"
|
|
32313
|
-
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
|
|
32314
|
-
label: "Show tooltips",
|
|
32315
|
-
checked: this.props.showTooltips,
|
|
32316
|
-
onChange: value => {
|
|
32317
|
-
this.change({
|
|
32318
|
-
showTooltips: value
|
|
32319
|
-
});
|
|
32320
|
-
}
|
|
32321
|
-
}))), /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
32322
|
-
label: "Background image URL:",
|
|
32323
|
-
style: styles$j.resetSpaceTop
|
|
32324
|
-
}, /*#__PURE__*/React__namespace.createElement("input", {
|
|
32325
|
-
type: "text",
|
|
32326
|
-
className: aphrodite.css(styles$j.backgroundUrlInput),
|
|
32327
|
-
ref: this.bgUrlRef,
|
|
32328
|
-
value: this.state.backgroundImage.url || "",
|
|
32329
|
-
onChange: e => {
|
|
32330
|
-
// Shallow-copied clone
|
|
32331
|
-
const image = {
|
|
32332
|
-
...this.props.backgroundImage
|
|
32333
|
-
};
|
|
32334
|
-
image.url = e.target.value;
|
|
32335
|
-
this.setState({
|
|
32336
|
-
backgroundImage: image
|
|
32337
|
-
});
|
|
32338
|
-
},
|
|
32339
|
-
onKeyPress: this.changeBackgroundUrl,
|
|
32340
|
-
onBlur: this.changeBackgroundUrl
|
|
32341
|
-
}), /*#__PURE__*/React__namespace.createElement(InfoTip$c, null, /*#__PURE__*/React__namespace.createElement("p", null, "Create an image in graphie, or use the \"Add image\" function to create a background."))), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
32342
|
-
style: styles$j.protractorSection
|
|
32343
|
-
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
32344
|
-
style: styles$j.checkboxRow
|
|
32345
|
-
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksForm.Checkbox, {
|
|
32346
|
-
label: "Show protractor",
|
|
32347
|
-
checked: this.props.showProtractor,
|
|
32348
|
-
onChange: value => {
|
|
32349
|
-
this.change({
|
|
32350
|
-
showProtractor: value
|
|
32351
|
-
});
|
|
32352
|
-
},
|
|
32353
|
-
style: styles$j.resetSpaceTop
|
|
32354
|
-
})), this.props.showProtractor && /*#__PURE__*/React__namespace.createElement(Banner__default["default"], {
|
|
32355
|
-
layout: "floating",
|
|
32356
|
-
text: "The protractor is not accessible. Please consider an alternate approach.",
|
|
32357
|
-
kind: "warning"
|
|
32358
|
-
}))));
|
|
32302
|
+
// Update expanded states
|
|
32303
|
+
const newExpandedStates = [...expandedStates];
|
|
32304
|
+
newExpandedStates.splice(index, 1);
|
|
32305
|
+
setExpandedStates(newExpandedStates);
|
|
32306
|
+
}
|
|
32359
32307
|
}
|
|
32360
|
-
|
|
32361
|
-
|
|
32362
|
-
|
|
32363
|
-
|
|
32364
|
-
|
|
32365
|
-
|
|
32366
|
-
|
|
32367
|
-
|
|
32368
|
-
|
|
32369
|
-
|
|
32370
|
-
|
|
32308
|
+
function changeProps(index,
|
|
32309
|
+
// Omit the type from the figure props so it doesn't think
|
|
32310
|
+
// we're trying to pass in the props for the wrong type.
|
|
32311
|
+
figureProps) {
|
|
32312
|
+
const lockedFigures = figures || [];
|
|
32313
|
+
const newFigures = {
|
|
32314
|
+
lockedFigures: [...lockedFigures.slice(0, index), {
|
|
32315
|
+
...lockedFigures[index],
|
|
32316
|
+
...figureProps
|
|
32317
|
+
}, ...lockedFigures.slice(index + 1)]
|
|
32318
|
+
};
|
|
32319
|
+
onChange(newFigures);
|
|
32320
|
+
}
|
|
32321
|
+
function toggleExpanded(newValue) {
|
|
32322
|
+
setExpandedStates(Array(figures?.length).fill(newValue));
|
|
32323
|
+
}
|
|
32324
|
+
const allCollapsed = expandedStates.every(value => !value);
|
|
32325
|
+
const buttonLabel = allCollapsed ? "Expand all" : "Collapse all";
|
|
32326
|
+
const showExpandButton = !!figures?.length;
|
|
32327
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(Heading, {
|
|
32328
|
+
title: "Locked Figures",
|
|
32329
|
+
isOpen: isExpanded,
|
|
32330
|
+
onToggle: () => setIsExpanded(!isExpanded),
|
|
32331
|
+
isCollapsible: true
|
|
32332
|
+
}), isExpanded && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, figures?.map((figure, index) => {
|
|
32333
|
+
return /*#__PURE__*/React__namespace.createElement(LockedFigureSettings, _extends({
|
|
32334
|
+
key: `${uniqueId}-locked-${figure}-${index}`,
|
|
32335
|
+
flags: props.flags,
|
|
32336
|
+
showLabelsFlag: props.showLabelsFlag,
|
|
32337
|
+
expanded: expandedStates[index],
|
|
32338
|
+
onToggle: newValue => {
|
|
32339
|
+
const newExpanded = [...expandedStates];
|
|
32340
|
+
newExpanded[index] = newValue;
|
|
32341
|
+
setExpandedStates(newExpanded);
|
|
32342
|
+
}
|
|
32343
|
+
}, figure, {
|
|
32344
|
+
onChangeProps: newProps => changeProps(index, newProps),
|
|
32345
|
+
onMove: movement => moveLockedFigure(index, movement),
|
|
32346
|
+
onRemove: () => removeLockedFigure(index)
|
|
32347
|
+
}));
|
|
32348
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
32349
|
+
style: styles$i.buttonContainer
|
|
32350
|
+
}, /*#__PURE__*/React__namespace.createElement(LockedFigureSelect, {
|
|
32351
|
+
showLabelsFlag: props.showLabelsFlag,
|
|
32352
|
+
id: `${uniqueId}-select`,
|
|
32353
|
+
onChange: addLockedFigure
|
|
32354
|
+
}), /*#__PURE__*/React__namespace.createElement(Strut, {
|
|
32355
|
+
size: wonderBlocksTokens.spacing.small_12
|
|
32356
|
+
}), showExpandButton && /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
|
|
32357
|
+
kind: "secondary",
|
|
32358
|
+
onClick: () => toggleExpanded(allCollapsed),
|
|
32359
|
+
style: styles$i.button
|
|
32360
|
+
}, buttonLabel))));
|
|
32361
|
+
};
|
|
32362
|
+
const styles$i = aphrodite.StyleSheet.create({
|
|
32363
|
+
buttonContainer: {
|
|
32371
32364
|
flexDirection: "row",
|
|
32372
|
-
alignItems: "center"
|
|
32373
|
-
justifyContent: "space-between",
|
|
32374
|
-
marginBottom: wonderBlocksTokens.spacing.xSmall_8
|
|
32365
|
+
alignItems: "center"
|
|
32375
32366
|
},
|
|
32376
|
-
|
|
32367
|
+
button: {
|
|
32377
32368
|
marginTop: wonderBlocksTokens.spacing.xSmall_8,
|
|
32378
|
-
|
|
32379
|
-
paddingTop: wonderBlocksTokens.spacing.xSmall_8,
|
|
32380
|
-
paddingBottom: wonderBlocksTokens.spacing.xSmall_8,
|
|
32381
|
-
borderBottom: `1px solid ${wonderBlocksTokens.color.offBlack16}`
|
|
32369
|
+
flexGrow: 1
|
|
32382
32370
|
}
|
|
32383
32371
|
});
|
|
32384
32372
|
|
|
32385
|
-
|
|
32386
|
-
|
|
32387
|
-
|
|
32388
|
-
|
|
32389
|
-
|
|
32390
|
-
|
|
32391
|
-
|
|
32392
|
-
|
|
32393
|
-
|
|
32394
|
-
|
|
32395
|
-
|
|
32396
|
-
|
|
32397
|
-
|
|
32398
|
-
|
|
32399
|
-
|
|
32400
|
-
|
|
32401
|
-
|
|
32402
|
-
|
|
32403
|
-
|
|
32404
|
-
|
|
32405
|
-
|
|
32373
|
+
function getStartCoords(graph) {
|
|
32374
|
+
if ("startCoords" in graph) {
|
|
32375
|
+
return graph.startCoords;
|
|
32376
|
+
}
|
|
32377
|
+
return undefined;
|
|
32378
|
+
}
|
|
32379
|
+
function getDefaultGraphStartCoords(graph, range, step) {
|
|
32380
|
+
switch (graph.type) {
|
|
32381
|
+
case "linear":
|
|
32382
|
+
case "ray":
|
|
32383
|
+
return perseus.getLineCoords({
|
|
32384
|
+
...graph,
|
|
32385
|
+
startCoords: undefined
|
|
32386
|
+
}, range, step);
|
|
32387
|
+
case "segment":
|
|
32388
|
+
return perseus.getSegmentCoords({
|
|
32389
|
+
...graph,
|
|
32390
|
+
startCoords: undefined
|
|
32391
|
+
}, range, step);
|
|
32392
|
+
case "linear-system":
|
|
32393
|
+
return perseus.getLinearSystemCoords({
|
|
32394
|
+
...graph,
|
|
32395
|
+
startCoords: undefined
|
|
32396
|
+
}, range, step);
|
|
32397
|
+
case "circle":
|
|
32398
|
+
const startCoords = perseus.getCircleCoords({
|
|
32399
|
+
...graph,
|
|
32400
|
+
startCoords: undefined
|
|
32401
|
+
});
|
|
32402
|
+
const radius = kmath.vector.length(kmath.vector.subtract(startCoords.radiusPoint, startCoords.center));
|
|
32403
|
+
return {
|
|
32404
|
+
center: startCoords.center,
|
|
32405
|
+
radius
|
|
32406
|
+
};
|
|
32407
|
+
case "sinusoid":
|
|
32408
|
+
return perseus.getSinusoidCoords({
|
|
32409
|
+
...graph,
|
|
32410
|
+
startCoords: undefined
|
|
32411
|
+
}, range, step);
|
|
32412
|
+
case "quadratic":
|
|
32413
|
+
return perseus.getQuadraticCoords({
|
|
32414
|
+
...graph,
|
|
32415
|
+
startCoords: undefined
|
|
32416
|
+
}, range, step);
|
|
32417
|
+
case "point":
|
|
32418
|
+
return perseus.getPointCoords({
|
|
32419
|
+
...graph,
|
|
32420
|
+
startCoords: undefined
|
|
32421
|
+
}, range, step);
|
|
32422
|
+
case "polygon":
|
|
32423
|
+
return perseus.getPolygonCoords({
|
|
32424
|
+
...graph,
|
|
32425
|
+
startCoords: undefined
|
|
32426
|
+
}, range, step);
|
|
32427
|
+
case "angle":
|
|
32428
|
+
return perseus.getAngleCoords({
|
|
32429
|
+
graph: {
|
|
32430
|
+
...graph,
|
|
32431
|
+
startCoords: undefined
|
|
32432
|
+
},
|
|
32433
|
+
range,
|
|
32434
|
+
step
|
|
32435
|
+
});
|
|
32436
|
+
default:
|
|
32437
|
+
return undefined;
|
|
32438
|
+
}
|
|
32439
|
+
}
|
|
32440
|
+
const getSinusoidEquation = startCoords => {
|
|
32441
|
+
// Get coefficients
|
|
32442
|
+
// It's assumed that p1 is the root and p2 is the first peak
|
|
32443
|
+
const p1 = startCoords[0];
|
|
32444
|
+
const p2 = startCoords[1];
|
|
32445
|
+
|
|
32446
|
+
// Resulting coefficients are canonical for this sine curve
|
|
32447
|
+
const amplitude = p2[1] - p1[1];
|
|
32448
|
+
const angularFrequency = Math.PI / (2 * (p2[0] - p1[0]));
|
|
32449
|
+
const phase = p1[0] * angularFrequency;
|
|
32450
|
+
const verticalOffset = p1[1];
|
|
32451
|
+
return "y = " + amplitude.toFixed(3) + "sin(" + angularFrequency.toFixed(3) + "x - " + phase.toFixed(3) + ") + " + verticalOffset.toFixed(3);
|
|
32406
32452
|
};
|
|
32407
|
-
const
|
|
32408
|
-
|
|
32409
|
-
|
|
32410
|
-
|
|
32411
|
-
|
|
32453
|
+
const getQuadraticEquation = startCoords => {
|
|
32454
|
+
const p1 = startCoords[0];
|
|
32455
|
+
const p2 = startCoords[1];
|
|
32456
|
+
const p3 = startCoords[2];
|
|
32457
|
+
const denom = (p1[0] - p2[0]) * (p1[0] - p3[0]) * (p2[0] - p3[0]);
|
|
32458
|
+
if (denom === 0) {
|
|
32459
|
+
// Many of the callers assume that the return value is always defined.
|
|
32460
|
+
return "Division by zero error";
|
|
32412
32461
|
}
|
|
32413
|
-
|
|
32462
|
+
const a = (p3[0] * (p2[1] - p1[1]) + p2[0] * (p1[1] - p3[1]) + p1[0] * (p3[1] - p2[1])) / denom;
|
|
32463
|
+
const b = (p3[0] * p3[0] * (p1[1] - p2[1]) + p2[0] * p2[0] * (p3[1] - p1[1]) + p1[0] * p1[0] * (p2[1] - p3[1])) / denom;
|
|
32464
|
+
const c = (p2[0] * p3[0] * (p2[0] - p3[0]) * p1[1] + p3[0] * p1[0] * (p3[0] - p1[0]) * p2[1] + p1[0] * p2[0] * (p1[0] - p2[0]) * p3[1]) / denom;
|
|
32465
|
+
return "y = " + a.toFixed(3) + "x^2 + " + b.toFixed(3) + "x + " + c.toFixed(3);
|
|
32466
|
+
};
|
|
32467
|
+
const findAngle = (point1, point2) => {
|
|
32468
|
+
const x = point1[0] - point2[0];
|
|
32469
|
+
const y = point1[1] - point2[1];
|
|
32470
|
+
return (180 + Math.atan2(-y, -x) * 180 / Math.PI + 360) % 360;
|
|
32471
|
+
};
|
|
32472
|
+
const getAngleEquation = startCoords => {
|
|
32473
|
+
const [point1, vertex, point2] = startCoords;
|
|
32474
|
+
const angle = findAngle(point2, vertex) - findAngle(point1, vertex);
|
|
32475
|
+
const roundedAngle = angle.toFixed(0);
|
|
32476
|
+
return `${roundedAngle}\u00B0 angle at (${vertex[0]}, ${vertex[1]})`;
|
|
32477
|
+
};
|
|
32478
|
+
const shouldShowStartCoordsUI = (graph, isStatic) => {
|
|
32479
|
+
// We don't show the start coords UI for static graphs, since
|
|
32480
|
+
// the coords shown for this are determined by the coords on the
|
|
32481
|
+
// "correct" graph. The start coords would not be used here.
|
|
32482
|
+
if (isStatic) {
|
|
32483
|
+
return false;
|
|
32484
|
+
}
|
|
32485
|
+
switch (graph.type) {
|
|
32486
|
+
case "point":
|
|
32487
|
+
return graph.numPoints !== "unlimited";
|
|
32488
|
+
case "polygon":
|
|
32489
|
+
return graph.numSides !== "unlimited" && graph.snapTo !== "angles" && graph.snapTo !== "sides";
|
|
32490
|
+
case "none":
|
|
32491
|
+
return false;
|
|
32492
|
+
case "angle":
|
|
32493
|
+
case "circle":
|
|
32494
|
+
case "linear":
|
|
32495
|
+
case "linear-system":
|
|
32496
|
+
case "quadratic":
|
|
32497
|
+
case "ray":
|
|
32498
|
+
case "segment":
|
|
32499
|
+
case "sinusoid":
|
|
32500
|
+
return true;
|
|
32501
|
+
default:
|
|
32502
|
+
throw new wonderStuffCore.UnreachableCaseError(graph);
|
|
32503
|
+
}
|
|
32504
|
+
};
|
|
32414
32505
|
|
|
32415
32506
|
const StartCoordsAngle = props => {
|
|
32416
32507
|
const {
|
|
@@ -32922,7 +33013,7 @@ class InteractiveGraphEditor extends React__namespace.Component {
|
|
|
32922
33013
|
___default["default"].extend(json, {
|
|
32923
33014
|
graph: {
|
|
32924
33015
|
type: correct.type,
|
|
32925
|
-
startCoords: this.props.graph
|
|
33016
|
+
startCoords: this.props.graph && getStartCoords(this.props.graph)
|
|
32926
33017
|
},
|
|
32927
33018
|
correct: correct
|
|
32928
33019
|
});
|
|
@@ -33017,7 +33108,7 @@ class InteractiveGraphEditor extends React__namespace.Component {
|
|
|
33017
33108
|
}, this.props.valid);
|
|
33018
33109
|
}
|
|
33019
33110
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(LabeledRow, {
|
|
33020
|
-
label: "
|
|
33111
|
+
label: "Answer type:"
|
|
33021
33112
|
}, /*#__PURE__*/React__namespace.createElement(GraphTypeSelector, {
|
|
33022
33113
|
graphType: this.props.graph?.type ?? InteractiveGraph.defaultProps.graph.type,
|
|
33023
33114
|
onChange: type => {
|
|
@@ -33029,7 +33120,8 @@ class InteractiveGraphEditor extends React__namespace.Component {
|
|
|
33029
33120
|
type
|
|
33030
33121
|
}
|
|
33031
33122
|
});
|
|
33032
|
-
}
|
|
33123
|
+
},
|
|
33124
|
+
showNoneOption: this.props.apiOptions?.flags?.mafs?.["none"]
|
|
33033
33125
|
})), this.props.graph && this.props.apiOptions?.flags?.mafs?.[this.props.graph.type] && /*#__PURE__*/React__namespace.createElement(InteractiveGraphDescription, {
|
|
33034
33126
|
ariaLabelValue: this.props.fullGraphAriaLabel ?? "",
|
|
33035
33127
|
ariaDescriptionValue: this.props.fullGraphAriaDescription ?? "",
|
|
@@ -33266,6 +33358,7 @@ class InteractiveGraphEditor extends React__namespace.Component {
|
|
|
33266
33358
|
// Only show the "Add locked figure" dropdown if the graph
|
|
33267
33359
|
// is using Mafs.
|
|
33268
33360
|
this.props.graph && this.props.apiOptions?.flags?.mafs?.[this.props.graph.type] && /*#__PURE__*/React__namespace.createElement(LockedFiguresSection, {
|
|
33361
|
+
flags: this.props.apiOptions.flags,
|
|
33269
33362
|
showLabelsFlag: this.props.apiOptions?.flags?.mafs?.["interactive-graph-locked-features-labels"],
|
|
33270
33363
|
figures: this.props.lockedFigures,
|
|
33271
33364
|
onChange: this.props.onChange
|
|
@@ -33305,6 +33398,12 @@ function mergeGraphs(a, b) {
|
|
|
33305
33398
|
...a,
|
|
33306
33399
|
...b
|
|
33307
33400
|
};
|
|
33401
|
+
case "none":
|
|
33402
|
+
invariant(b.type === "none");
|
|
33403
|
+
return {
|
|
33404
|
+
...a,
|
|
33405
|
+
...b
|
|
33406
|
+
};
|
|
33308
33407
|
case "point":
|
|
33309
33408
|
invariant(b.type === "point");
|
|
33310
33409
|
return {
|
|
@@ -37156,14 +37255,6 @@ class TableEditor extends React__namespace.Component {
|
|
|
37156
37255
|
});
|
|
37157
37256
|
};
|
|
37158
37257
|
render() {
|
|
37159
|
-
const tableProps = ___default["default"].pick(this.props, "headers", "answers", "onChange", "apiOptions");
|
|
37160
|
-
___default["default"].extend(tableProps, {
|
|
37161
|
-
editableHeaders: true,
|
|
37162
|
-
Editor,
|
|
37163
|
-
onFocus: () => {},
|
|
37164
|
-
onBlur: () => {},
|
|
37165
|
-
trackInteraction: () => {}
|
|
37166
|
-
});
|
|
37167
37258
|
return /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("div", {
|
|
37168
37259
|
className: "perseus-widget-row"
|
|
37169
37260
|
}, /*#__PURE__*/React__namespace.createElement("label", null, "Number of columns:", " ", /*#__PURE__*/React__namespace.createElement(NumberInput, {
|
|
@@ -37188,7 +37279,17 @@ class TableEditor extends React__namespace.Component {
|
|
|
37188
37279
|
}
|
|
37189
37280
|
},
|
|
37190
37281
|
useArrowKeys: true
|
|
37191
|
-
}))), /*#__PURE__*/React__namespace.createElement("div", null, " ", "Table of answers:", " ", /*#__PURE__*/React__namespace.createElement(InfoTip$1, null, /*#__PURE__*/React__namespace.createElement("p", null, "The student has to fill out all cells in the table. For partially filled tables create a table using the template, and insert text input boxes as desired."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(Table,
|
|
37282
|
+
}))), /*#__PURE__*/React__namespace.createElement("div", null, " ", "Table of answers:", " ", /*#__PURE__*/React__namespace.createElement(InfoTip$1, null, /*#__PURE__*/React__namespace.createElement("p", null, "The student has to fill out all cells in the table. For partially filled tables create a table using the template, and insert text input boxes as desired."))), /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(Table, {
|
|
37283
|
+
headers: this.props.headers,
|
|
37284
|
+
answers: this.props.answers,
|
|
37285
|
+
onChange: this.props.onChange,
|
|
37286
|
+
apiOptions: this.props.apiOptions,
|
|
37287
|
+
editableHeaders: true,
|
|
37288
|
+
onFocus: () => {},
|
|
37289
|
+
onBlur: () => {},
|
|
37290
|
+
trackInteraction: () => {},
|
|
37291
|
+
Editor: Editor
|
|
37292
|
+
})));
|
|
37192
37293
|
}
|
|
37193
37294
|
}
|
|
37194
37295
|
|