@khanacademy/perseus 33.1.0 → 33.2.1

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/es/index.js CHANGED
@@ -8673,10 +8673,10 @@ var Raphael$1 = (function () {
8673
8673
  * provided on KhanUtil.
8674
8674
  */
8675
8675
  const KhanColors = {
8676
- BLUE: "#6495ED",
8676
+ BLUE: color.blue,
8677
8677
  ORANGE: "#FFA500",
8678
8678
  PINK: "#FF00AF",
8679
- GREEN: "#28AE7B",
8679
+ GREEN: color.green,
8680
8680
  PURPLE: "#9D38BD",
8681
8681
  RED: "#DF0030",
8682
8682
  GRAY: "gray",
@@ -8752,11 +8752,9 @@ const KhanColors = {
8752
8752
  // of any redesigns.
8753
8753
  _BACKGROUND: "#FDFDFD",
8754
8754
  // TODO(eater): Get rid of this altogether.
8755
- INTERACTING: "#71B307",
8756
- // KA_GREEN
8757
- INTERACTIVE: "#71B307",
8758
- // KA_GREEN
8759
- DYNAMIC: "#6495ED" // BLUE
8755
+ INTERACTING: color.green,
8756
+ INTERACTIVE: color.green,
8757
+ DYNAMIC: color.blue
8760
8758
  };
8761
8759
 
8762
8760
  // DrawingTransform is responsible for transforming from "math coordinates"
@@ -10036,21 +10034,50 @@ const setLabelMargins = function setLabelMargins(span, size) {
10036
10034
  });
10037
10035
  } else {
10038
10036
  var _$container$css, _$container$width, _$span$css;
10039
- const $container = $span.closest(".svg-image");
10037
+ // We are using jQuery to collect information and calculate a scale
10038
+ // since we don't have a way to pass it to this function.
10039
+ // We need the width of the container in order to calculate the scale to apply to the label.
10040
+ // Unfortunately, the DOM tree leading to the label is not consistent.
10041
+ // Therefore, we need to check different elements and different style properties to get the width of the container.
10042
+ // Some graphie labels exist within an ".svg-image" container, and others do not.
10043
+ // All graphie labels have a ".graphie" container.
10044
+ // When a label has an ".svg-image" container,
10045
+ // the width information in the ".graphie" element is expressed as a percentage instead of pixels,
10046
+ // so we can't use it.
10047
+ // Instead, the ".svg-image" container can be used to get the width information.
10048
+ // The following lines determine which container element to use for the width measurement.
10049
+ const $svgImage = $span.closest(".svg-image");
10050
+ const $graphie = $span.closest(".graphie");
10051
+ // If an ".svg-image" container exists in the DOM tree, then use it, otherwise use the ".graphie" container.
10052
+ const $container = $svgImage.length > 0 ? $svgImage : $graphie;
10053
+
10040
10054
  // Ensuring that the line-height of the text doesn't throw off placement of the text element.
10041
10055
  // Inherited line-height values can really mess up placement.
10042
10056
  $container.css("line-height", "normal");
10043
10057
 
10044
- // The 'max-width' value is the same as the expected (100% scale) width of the graphie.
10045
- // We are using jQuery to get this information since we don't have a way to pass it to this function.
10046
- const expectedWidth = (_$container$css = $container.css("max-width")) != null ? _$container$css : "0px";
10058
+ // The expected width of the graphie is found in the "max-width" property on ".svg-image" containers,
10059
+ // and is found in the "width" property on ".graphie" containers.
10060
+ const widthValues = (_$container$css = $container.css(["max-width", "width"])) != null ? _$container$css : {
10061
+ // The browser will always return a value, but tests won't, so ensuring something is returned.
10062
+ "max-width": "0px"
10063
+ };
10064
+ const expectedWidth =
10065
+ // Verified in Chrome, Firefox, and Safari - all return the same "none" value if the property does not exist.
10066
+ widthValues["max-width"] !== "none" ? widthValues["max-width"] : widthValues["width"];
10047
10067
  // We can calculate the true scale of the graphie by taking actual width and dividing by the expected width.
10048
- // NOTE: Using 'slice' to remove the "px" unit from the end of the expected width value.
10049
- const scale = ((_$container$width = $container.width()) != null ? _$container$width : 0) / parseInt(expectedWidth.replace(/px$/, "")) * 100;
10068
+ // NOTE: Using 'replace' to remove the "px" unit from the end of the expected width value.
10069
+ let scale = ((_$container$width = $container.width()) != null ? _$container$width : 0) / parseInt(expectedWidth.replace(/px$/, "")) * 100;
10070
+ // If something failed in the calculation, then default to 100% scale.
10071
+ if (isNaN(scale)) {
10072
+ scale = 100;
10073
+ } else if (scale === 0) {
10074
+ scale = 100;
10075
+ }
10050
10076
 
10051
10077
  // Any padding needs to be scaled accordingly.
10052
- const currentPadding = (_$span$css = $span.css("padding")) != null ? _$span$css : "0px";
10053
- const newPadding = Math.round(parseInt(currentPadding.slice(0, -2)) * scale) / 100;
10078
+ const padding = (_$span$css = $span.css("padding")) != null ? _$span$css : "0px";
10079
+ const currentPadding = padding !== "none" ? padding : "0px";
10080
+ const newPadding = Math.round(parseInt(currentPadding.replace(/px$/, "")) * scale) / 100;
10054
10081
 
10055
10082
  // "multipliers" basically move the position of the text by using 1, 0, -1
10056
10083
  // 'margin-left' and 'margin-top' are used to position the text.
@@ -29639,7 +29666,8 @@ function LockedLabel(props) {
29639
29666
  left: x,
29640
29667
  top: y,
29641
29668
  color: lockedFigureColors[color],
29642
- fontSize: font.size[size]
29669
+ fontSize: font.size[size],
29670
+ backgroundColor: "rgba(255, 255, 255, 0.8)"
29643
29671
  }
29644
29672
  }, /*#__PURE__*/React.createElement(TeX, null, text));
29645
29673
  }
@@ -31657,7 +31685,8 @@ function UnlimitedPointGraph(props) {
31657
31685
  const [[left, top]] = useTransformVectorsToPixels([minX, maxY]);
31658
31686
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("rect", {
31659
31687
  style: {
31660
- fill: "rgba(0,0,0,0)"
31688
+ fill: "rgba(0,0,0,0)",
31689
+ cursor: "crosshair"
31661
31690
  },
31662
31691
  width: widthPx,
31663
31692
  height: heightPx,
@@ -31827,6 +31856,17 @@ function useDraggablePx(args) {
31827
31856
  });
31828
31857
  }
31829
31858
 
31859
+ /**
31860
+ * Render the Mafs graph with the specified background and graph elements.
31861
+ *
31862
+ * Render order (back to front):
31863
+ * - Grid
31864
+ * - Axis Ticks, Axis Arrows, and Axis Labels
31865
+ * - Locked Figures
31866
+ * - Locked Labels
31867
+ * - Protractor
31868
+ * - Interactive Graph Elements
31869
+ */
31830
31870
  const MafsGraph = props => {
31831
31871
  const {
31832
31872
  state,
@@ -31906,8 +31946,6 @@ const MafsGraph = props => {
31906
31946
  }, fullGraphAriaDescription), /*#__PURE__*/React.createElement(LegacyGrid, {
31907
31947
  box: props.box,
31908
31948
  backgroundImage: props.backgroundImage
31909
- }), props.showLabelsFlag && props.lockedFigures && /*#__PURE__*/React.createElement(GraphLockedLabelsLayer, {
31910
- lockedFigures: props.lockedFigures
31911
31949
  }), /*#__PURE__*/React.createElement(View, {
31912
31950
  style: {
31913
31951
  position: "absolute",
@@ -31937,28 +31975,64 @@ const MafsGraph = props => {
31937
31975
  props.markings === "graph" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(AxisTicks, null), /*#__PURE__*/React.createElement(AxisArrows, null)), /*#__PURE__*/React.createElement("svg", nestedSVGAttributes, props.lockedFigures && /*#__PURE__*/React.createElement(GraphLockedLayer, {
31938
31976
  lockedFigures: props.lockedFigures,
31939
31977
  range: state.range
31940
- }), props.showProtractor && /*#__PURE__*/React.createElement(Protractor, null), renderGraph({
31978
+ }))), props.showLabelsFlag && props.lockedFigures && /*#__PURE__*/React.createElement(GraphLockedLabelsLayer, {
31979
+ lockedFigures: props.lockedFigures
31980
+ }), /*#__PURE__*/React.createElement(View, {
31981
+ style: {
31982
+ position: "absolute"
31983
+ }
31984
+ }, /*#__PURE__*/React.createElement(Mafs, {
31985
+ preserveAspectRatio: false,
31986
+ viewBox: {
31987
+ x: state.range[X],
31988
+ y: state.range[Y],
31989
+ padding: 0
31990
+ },
31991
+ pan: false,
31992
+ zoom: false,
31993
+ width: width,
31994
+ height: height
31995
+ }, props.showProtractor && /*#__PURE__*/React.createElement(Protractor, null), renderGraph({
31941
31996
  state,
31942
31997
  dispatch
31943
31998
  }))))), renderGraphControls({
31944
31999
  state,
31945
- dispatch
32000
+ dispatch,
32001
+ width
31946
32002
  })));
31947
32003
  };
31948
- const renderPointGraphControls = props => /*#__PURE__*/React.createElement(Button, {
32004
+ const renderPointGraphControls = props => /*#__PURE__*/React.createElement(View, {
32005
+ style: {
32006
+ flexDirection: "row",
32007
+ width: props.width
32008
+ }
32009
+ }, /*#__PURE__*/React.createElement(Button, {
31949
32010
  kind: "secondary",
31950
32011
  style: {
31951
32012
  width: "100%",
31952
32013
  marginLeft: "20px"
31953
32014
  },
32015
+ tabIndex: 0,
31954
32016
  onClick: () => {
31955
32017
  props.dispatch(actions.pointGraph.addPoint([0, 0]));
31956
32018
  }
31957
- }, "Add Point");
32019
+ }, "Add Point"), (props.state.focusedPointIndex !== null || props.state.previouslyFocusedPointIndex !== null) && /*#__PURE__*/React.createElement(Button, {
32020
+ kind: "secondary",
32021
+ color: "destructive",
32022
+ tabIndex: 0,
32023
+ style: {
32024
+ width: "100%",
32025
+ marginLeft: "20px"
32026
+ },
32027
+ onClick: event => {
32028
+ props.dispatch(actions.pointGraph.removePoint(props.state.previouslyFocusedPointIndex));
32029
+ }
32030
+ }, "Remove Point"));
31958
32031
  const renderGraphControls = props => {
31959
32032
  const {
31960
32033
  state,
31961
- dispatch
32034
+ dispatch,
32035
+ width
31962
32036
  } = props;
31963
32037
  const {
31964
32038
  type
@@ -31968,7 +32042,8 @@ const renderGraphControls = props => {
31968
32042
  if (state.numPoints === "unlimited") {
31969
32043
  return renderPointGraphControls({
31970
32044
  state,
31971
- dispatch
32045
+ dispatch,
32046
+ width
31972
32047
  });
31973
32048
  }
31974
32049
  return null;
@@ -32137,7 +32212,8 @@ function initializeGraphState(params) {
32137
32212
  type: graph.type,
32138
32213
  coords: getPointCoords(graph, range, step),
32139
32214
  numPoints: graph.numPoints || 0,
32140
- focusedPointIndex: null
32215
+ focusedPointIndex: null,
32216
+ previouslyFocusedPointIndex: null
32141
32217
  });
32142
32218
  case "circle":
32143
32219
  return _extends({}, shared, {
@@ -32430,6 +32506,7 @@ function doBlurPoint(state, action) {
32430
32506
  switch (state.type) {
32431
32507
  case "point":
32432
32508
  return _extends({}, state, {
32509
+ previouslyFocusedPointIndex: state.focusedPointIndex,
32433
32510
  focusedPointIndex: null
32434
32511
  });
32435
32512
  default:
@@ -32474,7 +32551,6 @@ function doMovePointInFigure(state, action) {
32474
32551
  }
32475
32552
  case "angle":
32476
32553
  case "circle":
32477
- throw new Error("FIXME implement circle reducer");
32478
32554
  case "point":
32479
32555
  case "polygon":
32480
32556
  case "quadratic":
@@ -32785,7 +32861,8 @@ function doRemovePoint(state, action) {
32785
32861
  }
32786
32862
  return _extends({}, state, {
32787
32863
  coords: state.coords.filter((_, i) => i !== action.index),
32788
- focusedPointIndex: null
32864
+ focusedPointIndex: null,
32865
+ previouslyFocusedPointIndex: null
32789
32866
  });
32790
32867
  }
32791
32868
  const getDeltaVertex = (maxMoves, minMoves, delta) => {
@@ -39612,15 +39689,15 @@ const TickMarks = Graphie.createSimpleClass((graphie, props) => {
39612
39689
 
39613
39690
  // Render the text labels
39614
39691
  results.push(graphie.style(props.isMobile ? {
39615
- color: KhanColors.BLUE_D
39692
+ color: KhanColors.BLUE
39616
39693
  } : {}, () => _label(graphie, props.labelStyle, leftLabel, leftLabel, base)));
39617
39694
  results.push(graphie.style(props.isMobile ? {
39618
- color: KhanColors.BLUE_D
39695
+ color: KhanColors.BLUE
39619
39696
  } : {}, () => _label(graphie, props.labelStyle, rightLabel, rightLabel, base)));
39620
39697
 
39621
39698
  // Render the labels' lines
39622
39699
  graphie.style({
39623
- stroke: props.isMobile ? KhanColors.BLUE_D : KhanColors.DYNAMIC,
39700
+ stroke: KhanColors.BLUE,
39624
39701
  strokeWidth: 3.5
39625
39702
  }, () => {
39626
39703
  results.push(graphie.line([leftLabel, -0.2], [leftLabel, 0.2]));
@@ -39787,21 +39864,21 @@ class NumberLine extends React.Component {
39787
39864
  if (isOpen) {
39788
39865
  fill = KhanColors._BACKGROUND;
39789
39866
  } else if (props.static) {
39790
- fill = KhanColors.DYNAMIC;
39867
+ fill = KhanColors.BLUE;
39791
39868
  } else {
39792
- fill = KhanColors.INTERACTIVE;
39869
+ fill = KhanColors.GREEN;
39793
39870
  }
39794
39871
  const normalStyle = {
39795
39872
  fill: fill,
39796
- stroke: props.static ? KhanColors.DYNAMIC : KhanColors.INTERACTIVE,
39873
+ stroke: props.static ? KhanColors.BLUE : KhanColors.GREEN,
39797
39874
  "stroke-width": isOpen ? 3 : 1
39798
39875
  };
39799
39876
  const highlightStyle = {
39800
- fill: isOpen ? KhanColors._BACKGROUND : KhanColors.INTERACTING,
39877
+ fill: isOpen ? KhanColors._BACKGROUND : KhanColors.GREEN,
39801
39878
  "stroke-width": isOpen ? 3 : 1
39802
39879
  };
39803
39880
  const mobileDotStyle = props.isInequality ? {
39804
- stroke: KhanColors.INTERACTIVE,
39881
+ stroke: KhanColors.GREEN,
39805
39882
  "fill-opacity": isOpen ? 0 : 1
39806
39883
  } : {};
39807
39884
  return /*#__PURE__*/React.createElement(MovablePoint
@@ -39859,7 +39936,7 @@ class NumberLine extends React.Component {
39859
39936
  const end = this._getInequalityEndpoint(props);
39860
39937
  const style = {
39861
39938
  arrows: "->",
39862
- stroke: this.props.apiOptions.isMobile ? KhanColors.INTERACTIVE : KhanColors.DYNAMIC,
39939
+ stroke: this.props.apiOptions.isMobile ? KhanColors.GREEN : KhanColors.BLUE,
39863
39940
  strokeWidth: 3.5
39864
39941
  };
39865
39942
  const isGreater = ["ge", "gt"].includes(props.rel);
@@ -43048,7 +43125,7 @@ class PhetSimulation extends React.Component {
43048
43125
  className: css(styles$6.iframeResponsive),
43049
43126
  src: (_this$state$url = this.state.url) == null ? void 0 : _this$state$url.toString(),
43050
43127
  allow: "fullscreen"
43051
- })), /*#__PURE__*/React.createElement(IconButton, {
43128
+ })), this.state.url !== null && /*#__PURE__*/React.createElement(IconButton, {
43052
43129
  icon: cornersOutIcon,
43053
43130
  onClick: () => {
43054
43131
  var _this$iframeRef$curre;
@@ -43060,8 +43137,7 @@ class PhetSimulation extends React.Component {
43060
43137
  marginTop: 5,
43061
43138
  marginBottom: 5,
43062
43139
  alignSelf: "flex-end"
43063
- },
43064
- disabled: this.state.url === null
43140
+ }
43065
43141
  }));
43066
43142
  }
43067
43143
  }
@@ -44616,7 +44692,7 @@ const init = function init(options) {
44616
44692
 
44617
44693
  // This file is processed by a Rollup plugin (replace) to inject the production
44618
44694
  const libName = "@khanacademy/perseus";
44619
- const libVersion = "33.1.0";
44695
+ const libVersion = "33.2.1";
44620
44696
  addLibraryVersionToPerseusDebug(libName, libVersion);
44621
44697
 
44622
44698
  const apiVersion = {