@khanacademy/perseus 4.0.2 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/components/fixed-to-responsive.d.ts +27 -1
  3. package/dist/components/fixed-to-responsive.js.flow +27 -1
  4. package/dist/components/graph.d.ts +42 -26
  5. package/dist/components/graph.js.flow +42 -28
  6. package/dist/components/graphie.d.ts +34 -22
  7. package/dist/components/graphie.js.flow +37 -24
  8. package/dist/components/highlighting/highlightable-content.d.ts +4 -4
  9. package/dist/components/highlighting/highlightable-content.js.flow +4 -7
  10. package/dist/components/highlighting/ui/highlight-renderer.d.ts +6 -6
  11. package/dist/components/highlighting/ui/highlight-renderer.js.flow +6 -8
  12. package/dist/components/highlighting/ui/highlight-set-renderer.d.ts +5 -5
  13. package/dist/components/highlighting/ui/highlight-set-renderer.js.flow +5 -8
  14. package/dist/components/highlighting/ui/highlight-tooltip.d.ts +2 -2
  15. package/dist/components/highlighting/ui/highlight-tooltip.js.flow +2 -4
  16. package/dist/components/highlighting/ui/highlighting-ui.d.ts +2 -2
  17. package/dist/components/highlighting/ui/highlighting-ui.js.flow +2 -2
  18. package/dist/components/highlighting/ui/selection-tracker.d.ts +5 -5
  19. package/dist/components/highlighting/ui/selection-tracker.js.flow +5 -7
  20. package/dist/components/highlighting/word-indexer.d.ts +2 -2
  21. package/dist/components/highlighting/word-indexer.js.flow +2 -2
  22. package/dist/components/hud.d.ts +8 -14
  23. package/dist/components/hud.js.flow +7 -14
  24. package/dist/components/inline-icon.d.ts +27 -3
  25. package/dist/components/inline-icon.js.flow +26 -3
  26. package/dist/components/lint.d.ts +41 -13
  27. package/dist/components/lint.js.flow +42 -13
  28. package/dist/components/math-output.d.ts +15 -11
  29. package/dist/components/math-output.js.flow +15 -11
  30. package/dist/components/simple-keypad-input.d.ts +1 -1
  31. package/dist/components/simple-keypad-input.js.flow +1 -1
  32. package/dist/components/sortable.d.ts +17 -9
  33. package/dist/components/sortable.js.flow +22 -9
  34. package/dist/components/svg-image.d.ts +5 -3
  35. package/dist/components/svg-image.js.flow +5 -3
  36. package/dist/components/tex-buttons.d.ts +2 -2
  37. package/dist/components/tex-buttons.js.flow +2 -2
  38. package/dist/components/tooltip.d.ts +45 -4
  39. package/dist/components/tooltip.js.flow +44 -31
  40. package/dist/error-boundary.d.ts +4 -4
  41. package/dist/error-boundary.js.flow +4 -6
  42. package/dist/es/index.css +0 -3
  43. package/dist/es/index.js +484 -658
  44. package/dist/es/index.js.map +1 -1
  45. package/dist/index.css +0 -3
  46. package/dist/index.js +488 -655
  47. package/dist/index.js.map +1 -1
  48. package/dist/perseus-types.d.ts +11 -10
  49. package/dist/perseus-types.js.flow +11 -10
  50. package/dist/renderer.d.ts +2 -2
  51. package/dist/renderer.js.flow +1 -3
  52. package/dist/styles/shared.d.ts +0 -1
  53. package/dist/styles/shared.js.flow +0 -1
  54. package/dist/types.d.ts +0 -10
  55. package/dist/types.js.flow +0 -13
  56. package/dist/util/a11y.d.ts +0 -1
  57. package/dist/util/a11y.js.flow +0 -1
  58. package/dist/util/interactive.d.ts +2 -0
  59. package/dist/util/interactive.js.flow +2 -0
  60. package/dist/util.d.ts +3 -3
  61. package/dist/util.js.flow +4 -3
  62. package/dist/widgets/__stories__/test-keypad-context-wrapper.d.ts +2 -2
  63. package/dist/widgets/__stories__/test-keypad-context-wrapper.js.flow +2 -4
  64. package/dist/widgets/expression.d.ts +2 -2
  65. package/dist/widgets/expression.js.flow +2 -2
  66. package/dist/widgets/grapher.d.ts +1 -1
  67. package/dist/widgets/grapher.js.flow +12 -3
  68. package/dist/widgets/interaction/element-container.d.ts +5 -4
  69. package/dist/widgets/interaction/element-container.js.flow +6 -11
  70. package/dist/widgets/label-image/marker.d.ts +4 -4
  71. package/dist/widgets/label-image/marker.js.flow +4 -6
  72. package/dist/widgets/matcher.d.ts +7 -3
  73. package/dist/widgets/matcher.js.flow +7 -3
  74. package/dist/widgets/number-line.d.ts +1 -1
  75. package/dist/widgets/number-line.js.flow +1 -1
  76. package/dist/widgets/numeric-input.d.ts +0 -2
  77. package/dist/widgets/numeric-input.js.flow +0 -4
  78. package/dist/widgets/radio/base-radio.d.ts +7 -1
  79. package/dist/widgets/radio/base-radio.js.flow +7 -1
  80. package/dist/widgets/radio/choice-icon/choice-icon.d.ts +1 -1
  81. package/dist/widgets/radio/choice-icon/choice-icon.js.flow +1 -1
  82. package/dist/widgets/radio/choice-icon/cross-out-line.d.ts +2 -2
  83. package/dist/widgets/radio/choice-icon/cross-out-line.js.flow +2 -2
  84. package/dist/widgets/radio/focus-ring.d.ts +8 -1
  85. package/dist/widgets/radio/focus-ring.js.flow +8 -1
  86. package/dist/widgets/radio/option-status.d.ts +2 -2
  87. package/dist/widgets/radio/option-status.js.flow +2 -2
  88. package/dist/widgets/video-transcript-link.d.ts +1 -1
  89. package/dist/widgets/video-transcript-link.js.flow +1 -1
  90. package/package.json +4 -4
  91. package/src/__stories__/item-renderer.stories.tsx +2 -6
  92. package/src/__stories__/server-item-renderer.stories.tsx +2 -6
  93. package/src/__tests__/__snapshots__/item-renderer.test.tsx.snap +151 -159
  94. package/src/__tests__/__snapshots__/renderer.test.tsx.snap +358 -394
  95. package/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap +169 -189
  96. package/src/components/__stories__/button-group.stories.tsx +2 -6
  97. package/src/components/__stories__/fixed-to-responsive.stories.tsx +14 -16
  98. package/src/components/__stories__/graph.stories.tsx +3 -5
  99. package/src/components/__stories__/graphie.stories.tsx +3 -5
  100. package/src/components/__stories__/hud.stories.tsx +2 -6
  101. package/src/components/__stories__/icon.stories.tsx +1 -1
  102. package/src/components/__stories__/image-loader.stories.tsx +4 -4
  103. package/src/components/__stories__/info-tip.stories.tsx +2 -6
  104. package/src/components/__stories__/inline-icon.stories.tsx +4 -8
  105. package/src/components/__stories__/input-with-examples.stories.tsx +6 -10
  106. package/src/components/__stories__/lint.stories.tsx +62 -27
  107. package/src/components/__stories__/math-input.stories.tsx +4 -8
  108. package/src/components/__stories__/math-output.stories.tsx +3 -5
  109. package/src/components/__stories__/multi-button-group.stories.tsx +2 -6
  110. package/src/components/__stories__/number-input.stories.tsx +6 -8
  111. package/src/components/__stories__/prop-check-box.stories.tsx +9 -9
  112. package/src/components/__stories__/range-input.stories.tsx +4 -6
  113. package/src/components/__stories__/simple-keypad-input.stories.tsx +2 -4
  114. package/src/components/__stories__/sortable.stories.tsx +20 -20
  115. package/src/components/__stories__/stub-tag-editor.stories.tsx +5 -9
  116. package/src/components/__stories__/svg-image.stories.tsx +10 -18
  117. package/src/components/__stories__/tex.stories.tsx +1 -3
  118. package/src/components/__stories__/text-buttons.stories.tsx +10 -22
  119. package/src/components/__stories__/text-input.stories.tsx +4 -10
  120. package/src/components/__stories__/text-list-editor.stories.tsx +1 -3
  121. package/src/components/__stories__/tooltip.stories.tsx +52 -0
  122. package/src/components/__stories__/zoomable-tex.stories.tsx +6 -4
  123. package/src/components/__stories__/zoomable.stories.tsx +1 -3
  124. package/src/components/__tests__/__snapshots__/sortable.test.tsx.snap +114 -30
  125. package/src/components/__tests__/__snapshots__/sorter.test.tsx.snap +172 -204
  126. package/src/components/__tests__/sortable.test.tsx +54 -16
  127. package/src/components/__tests__/sorter.test.tsx +12 -9
  128. package/src/components/fixed-to-responsive.tsx +43 -38
  129. package/src/components/graph.tsx +95 -81
  130. package/src/components/graphie.tsx +62 -32
  131. package/src/components/highlighting/highlightable-content.tsx +4 -7
  132. package/src/components/highlighting/ui/highlight-renderer.tsx +6 -9
  133. package/src/components/highlighting/ui/highlight-set-renderer.tsx +5 -8
  134. package/src/components/highlighting/ui/highlight-tooltip.tsx +2 -2
  135. package/src/components/highlighting/ui/highlighting-ui.tsx +2 -2
  136. package/src/components/highlighting/ui/selection-tracker.tsx +5 -8
  137. package/src/components/highlighting/word-indexer.tsx +2 -2
  138. package/src/components/hud.tsx +104 -115
  139. package/src/components/inline-icon.tsx +17 -34
  140. package/src/components/input-with-examples.tsx +4 -4
  141. package/src/components/lint.tsx +47 -41
  142. package/src/components/math-output.tsx +17 -11
  143. package/src/components/simple-keypad-input.tsx +4 -4
  144. package/src/components/sortable.tsx +134 -94
  145. package/src/components/svg-image.tsx +10 -11
  146. package/src/components/tex-buttons.tsx +2 -2
  147. package/src/components/tooltip.tsx +189 -171
  148. package/src/components/visibility-observer/__stories__/visibility-observer.stories.tsx +1 -3
  149. package/src/error-boundary.tsx +4 -7
  150. package/src/interactive2/types.ts +2 -2
  151. package/src/multi-items/__stories__/multi-renderer.stories.tsx +1 -1
  152. package/src/multi-items/__tests__/__snapshots__/multi-renderer.test.tsx.snap +708 -764
  153. package/src/multi-items/__tests__/multi-renderer.test.tsx +2 -3
  154. package/src/perseus-types.ts +13 -12
  155. package/src/renderer.tsx +11 -22
  156. package/src/types.ts +0 -18
  157. package/src/util/graphie.ts +3 -3
  158. package/src/util/interactive.ts +18 -5
  159. package/src/util/tex.ts +13 -77
  160. package/src/util.ts +3 -4
  161. package/src/widgets/__stories__/categorizer.stories.tsx +1 -1
  162. package/src/widgets/__stories__/cs-program.stories.tsx +1 -1
  163. package/src/widgets/__stories__/definition.stories.tsx +3 -7
  164. package/src/widgets/__stories__/dropdown.stories.tsx +1 -1
  165. package/src/widgets/__stories__/explanation.stories.tsx +2 -2
  166. package/src/widgets/__stories__/expression.stories.tsx +5 -11
  167. package/src/widgets/__stories__/graded-group-set.stories.tsx +1 -1
  168. package/src/widgets/__stories__/graded-group.stories.tsx +1 -1
  169. package/src/widgets/__stories__/grapher.stories.tsx +7 -21
  170. package/src/widgets/__stories__/group.stories.tsx +1 -1
  171. package/src/widgets/__stories__/iframe.stories.tsx +1 -1
  172. package/src/widgets/__stories__/image.stories.tsx +1 -1
  173. package/src/widgets/__stories__/input-number.stories.tsx +3 -12
  174. package/src/widgets/__stories__/interaction.stories.tsx +1 -1
  175. package/src/widgets/__stories__/interactive-graph.stories.tsx +9 -9
  176. package/src/widgets/__stories__/matcher.stories.tsx +1 -1
  177. package/src/widgets/__stories__/matrix.stories.tsx +1 -1
  178. package/src/widgets/__stories__/number-line.stories.tsx +1 -1
  179. package/src/widgets/__stories__/numeric-input.stories.tsx +3 -5
  180. package/src/widgets/__stories__/orderer.stories.tsx +1 -1
  181. package/src/widgets/__stories__/passage-ref.stories.tsx +2 -2
  182. package/src/widgets/__stories__/passage.stories.tsx +3 -9
  183. package/src/widgets/__stories__/radio.stories.tsx +3 -5
  184. package/src/widgets/__stories__/sorter.stories.tsx +1 -1
  185. package/src/widgets/__stories__/test-keypad-context-wrapper.tsx +2 -4
  186. package/src/widgets/__stories__/transformer.stories.tsx +1 -1
  187. package/src/widgets/__stories__/unit.stories.tsx +1 -3
  188. package/src/widgets/__stories__/video-transcript-link.stories.tsx +2 -6
  189. package/src/widgets/__stories__/video.stories.tsx +1 -1
  190. package/src/widgets/__testdata__/group.testdata.ts +0 -2
  191. package/src/widgets/__tests__/__snapshots__/categorizer.test.ts.snap +717 -773
  192. package/src/widgets/__tests__/__snapshots__/cs-program.test.ts.snap +28 -36
  193. package/src/widgets/__tests__/__snapshots__/definition.test.ts.snap +52 -60
  194. package/src/widgets/__tests__/__snapshots__/dropdown.test.ts.snap +100 -108
  195. package/src/widgets/__tests__/__snapshots__/explanation.test.ts.snap +212 -260
  196. package/src/widgets/__tests__/__snapshots__/graded-group-set-jipt.test.ts.snap +613 -641
  197. package/src/widgets/__tests__/__snapshots__/graded-group-set.test.ts.snap +249 -261
  198. package/src/widgets/__tests__/__snapshots__/graded-group.test.ts.snap +671 -735
  199. package/src/widgets/__tests__/__snapshots__/grapher.test.ts.snap +2676 -2684
  200. package/src/widgets/__tests__/__snapshots__/group.test.tsx.snap +938 -1002
  201. package/src/widgets/__tests__/__snapshots__/iframe.test.ts.snap +28 -36
  202. package/src/widgets/__tests__/__snapshots__/image.test.ts.snap +227 -255
  203. package/src/widgets/__tests__/__snapshots__/input-number.test.ts.snap +353 -357
  204. package/src/widgets/__tests__/__snapshots__/interaction.test.ts.snap +255 -259
  205. package/src/widgets/__tests__/__snapshots__/interactive-graph.test.ts.snap +2401 -2433
  206. package/src/widgets/__tests__/__snapshots__/matcher.test.tsx.snap +600 -756
  207. package/src/widgets/__tests__/__snapshots__/matrix.test.ts.snap +420 -428
  208. package/src/widgets/__tests__/__snapshots__/number-line.test.ts.snap +762 -770
  209. package/src/widgets/__tests__/__snapshots__/numeric-input.test.ts.snap +373 -393
  210. package/src/widgets/__tests__/__snapshots__/orderer.test.ts.snap +116 -148
  211. package/src/widgets/__tests__/__snapshots__/passage-ref.test.ts.snap +289 -301
  212. package/src/widgets/__tests__/__snapshots__/passage.test.tsx.snap +1679 -1711
  213. package/src/widgets/__tests__/__snapshots__/radio.test.ts.snap +2692 -2960
  214. package/src/widgets/__tests__/__snapshots__/video.test.ts.snap +90 -98
  215. package/src/widgets/__tests__/group.test.tsx +0 -2
  216. package/src/widgets/__tests__/matcher.test.tsx +33 -9
  217. package/src/widgets/__tests__/radio/focus-ring.test.tsx +0 -1
  218. package/src/widgets/expression.tsx +12 -9
  219. package/src/widgets/grapher.tsx +3 -3
  220. package/src/widgets/image.tsx +2 -2
  221. package/src/widgets/interaction/element-container.tsx +7 -8
  222. package/src/widgets/interactive-graph.tsx +5 -5
  223. package/src/widgets/label-image/__stories__/answer-choices.stories.tsx +2 -4
  224. package/src/widgets/label-image/__stories__/marker.stories.tsx +9 -19
  225. package/src/widgets/label-image/marker.tsx +4 -4
  226. package/src/widgets/matcher.tsx +43 -24
  227. package/src/widgets/number-line.tsx +1 -1
  228. package/src/widgets/numeric-input.tsx +0 -3
  229. package/src/widgets/passage/passage-markdown.tsx +2 -2
  230. package/src/widgets/radio/__stories__/base-radio.stories.tsx +11 -19
  231. package/src/widgets/radio/__stories__/choice-icon.stories.tsx +9 -11
  232. package/src/widgets/radio/__stories__/choice-none-above.stories.tsx +1 -1
  233. package/src/widgets/radio/__stories__/choice.stories.tsx +4 -4
  234. package/src/widgets/radio/__stories__/focus-ring.stories.tsx +1 -1
  235. package/src/widgets/radio/__stories__/option-status.stories.tsx +2 -4
  236. package/src/widgets/radio/base-radio.tsx +1 -1
  237. package/src/widgets/radio/choice-icon/choice-icon.tsx +5 -5
  238. package/src/widgets/radio/choice-icon/cross-out-line.tsx +1 -3
  239. package/src/widgets/radio/choice-none-above.tsx +2 -2
  240. package/src/widgets/radio/choice.tsx +1 -3
  241. package/src/widgets/radio/focus-ring.tsx +1 -1
  242. package/src/widgets/radio/option-status.tsx +2 -4
  243. package/src/widgets/radio/widget.tsx +0 -1
  244. package/src/widgets/reaction-diagram.tsx +2 -2
  245. package/src/widgets/simulator.tsx +4 -6
  246. package/src/widgets/video-transcript-link.tsx +1 -1
  247. package/{tsconfig.json → tsconfig-build.json} +6 -6
  248. package/tsconfig-build.tsbuildinfo +1 -0
  249. package/tsconfig.tsbuildinfo +0 -1
@@ -1,4 +1,3 @@
1
- /* eslint-disable react/prop-types */
2
1
  /**
3
2
  * A wrapper for a component that would otherwise have a fixed width and
4
3
  * height, that magically makes it reponsive while preserving its aspect ratio.
@@ -15,41 +14,47 @@
15
14
  * </FixedToResponsive>
16
15
  */
17
16
  import classNames from "classnames";
18
- import createReactClass from "create-react-class";
19
- import PropTypes from "prop-types";
20
17
  import * as React from "react";
21
18
 
22
19
  import {negativePhoneMargin} from "../styles/constants";
23
20
 
24
21
  const MIN_VIEWPORT_HEIGHT = 480;
25
22
 
26
- const FixedToResponsive: any = createReactClass({
27
- displayName: "FixedToResponsive",
28
-
29
- propTypes: {
30
- width: PropTypes.number.isRequired,
31
- height: PropTypes.number.isRequired,
32
- className: PropTypes.string,
33
- constrainHeight: PropTypes.bool,
34
- allowFullBleed: PropTypes.bool,
35
- },
36
-
37
- getDefaultProps: function () {
38
- return {
39
- className: "",
40
- constrainHeight: false,
41
- allowFullBleed: false,
42
- };
43
- },
44
-
45
- getInitialState: function () {
46
- return {
47
- viewportHeight: null,
48
- viewportWidth: null,
49
- };
50
- },
51
-
52
- componentDidMount: function () {
23
+ type Props = {
24
+ width: number;
25
+ height: number;
26
+ children: React.ReactNode;
27
+ className?: string;
28
+ constrainHeight?: boolean;
29
+ allowFullBleed?: boolean;
30
+ };
31
+
32
+ type DefaultProps = {
33
+ className: Props["className"];
34
+ constrainHeight: Props["constrainHeight"];
35
+ allowFullBleed: Props["allowFullBleed"];
36
+ };
37
+
38
+ type State = {
39
+ viewportHeight: number | null;
40
+ viewportWidth: number | null;
41
+ };
42
+
43
+ class FixedToResponsive extends React.Component<Props, State> {
44
+ _isMounted = false;
45
+
46
+ static defaultProps: DefaultProps = {
47
+ className: "",
48
+ constrainHeight: false,
49
+ allowFullBleed: false,
50
+ };
51
+
52
+ state: State = {
53
+ viewportHeight: null,
54
+ viewportWidth: null,
55
+ };
56
+
57
+ componentDidMount() {
53
58
  // TODO(scottgrant): This is a hack to remove the deprecated call to
54
59
  // this.isMounted() but is still considered an anti-pattern.
55
60
  this._isMounted = true;
@@ -70,13 +75,13 @@ const FixedToResponsive: any = createReactClass({
70
75
  } else {
71
76
  this._cacheViewportSize();
72
77
  }
73
- },
78
+ }
74
79
 
75
- componentWillUnmount: function () {
80
+ componentWillUnmount() {
76
81
  this._isMounted = false;
77
- },
82
+ }
78
83
 
79
- _cacheViewportSize: function () {
84
+ _cacheViewportSize: () => void = (): void => {
80
85
  if (this._isMounted) {
81
86
  this.setState({
82
87
  viewportHeight: Math.max(
@@ -86,9 +91,9 @@ const FixedToResponsive: any = createReactClass({
86
91
  viewportWidth: window.innerWidth,
87
92
  });
88
93
  }
89
- },
94
+ };
90
95
 
91
- render: function () {
96
+ render() {
92
97
  // The ideal behavior for responsified, fixed size child components is
93
98
  // that they shrink when they need to (while preserving aspect ratio)
94
99
  // but never grow larger than their original dimensions. We accomplish
@@ -158,7 +163,7 @@ const FixedToResponsive: any = createReactClass({
158
163
  );
159
164
  }
160
165
  return container;
161
- },
162
- });
166
+ }
167
+ }
163
168
 
164
169
  export default FixedToResponsive;
@@ -1,10 +1,11 @@
1
- /* eslint-disable react/forbid-prop-types, react/no-unsafe, react/sort-comp */
1
+ /* eslint-disable react/no-unsafe */
2
2
  import $ from "jquery";
3
- import PropTypes from "prop-types";
4
3
  import * as React from "react";
5
4
  import ReactDOM from "react-dom";
6
5
  import _ from "underscore";
7
6
 
7
+ import {Coord} from "../interactive2/types";
8
+ import {PerseusImageBackground} from "../perseus-types";
8
9
  import {interactiveSizes} from "../styles/constants";
9
10
  import Util from "../util";
10
11
  import GraphUtils from "../util/graph-utils";
@@ -13,7 +14,7 @@ import SvgImage from "./svg-image";
13
14
 
14
15
  const defaultBackgroundImage = {
15
16
  url: null,
16
- } as const;
17
+ };
17
18
 
18
19
  /* Style objects */
19
20
  const defaultInstructionsStyle = {
@@ -38,7 +39,46 @@ function numSteps(range: any, step: any) {
38
39
  return Math.floor((range[1] - range[0]) / step);
39
40
  }
40
41
 
41
- class Graph extends React.Component<any> {
42
+ type Props = {
43
+ box: Readonly<[number, number]>;
44
+ labels: ReadonlyArray<string>;
45
+ range: Readonly<[Coord, Coord]>;
46
+ step: Readonly<[number, number]>;
47
+ gridStep: Readonly<[number, number]>;
48
+ snapStep: Readonly<[number, number]>;
49
+ markings: string;
50
+ backgroundImage: PerseusImageBackground;
51
+ showProtractor: boolean;
52
+ showRuler: boolean;
53
+ rulerLabel: string;
54
+ rulerTicks: number;
55
+ instructions?: string;
56
+ isMobile: boolean;
57
+
58
+ onGraphieUpdated?: (graphie: any) => void;
59
+ onClick?: (Coord) => void;
60
+ onMouseDown?: (Coord) => void;
61
+ onMouseUp?: (Coord) => void;
62
+ onMouseMove?: (Coord) => void;
63
+ setDrawingAreaAvailable?: (boolean) => void;
64
+ };
65
+
66
+ type DefaultProps = {
67
+ labels: Props["labels"];
68
+ range: Props["range"];
69
+ step: Props["step"];
70
+ gridStep: Props["gridStep"];
71
+ snapStep: Props["snapStep"];
72
+ markings: Props["markings"];
73
+ backgroundImage: Props["backgroundImage"];
74
+ showProtractor: Props["showProtractor"];
75
+ showRuler: Props["showRuler"];
76
+ rulerLabel: Props["rulerLabel"];
77
+ rulerTicks: Props["rulerTicks"];
78
+ isMobile: Props["isMobile"];
79
+ };
80
+
81
+ class Graph extends React.Component<Props> {
42
82
  protractor: any;
43
83
  ruler: any;
44
84
  _graphie: any;
@@ -47,29 +87,7 @@ class Graph extends React.Component<any> {
47
87
  // @ts-expect-error [FEI-5003] - TS2564 - Property '_shouldSetupGraphie' has no initializer and is not definitely assigned in the constructor.
48
88
  _shouldSetupGraphie: boolean;
49
89
 
50
- static propTypes = {
51
- box: PropTypes.array.isRequired,
52
- labels: PropTypes.arrayOf(PropTypes.string),
53
- range: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)),
54
- step: PropTypes.arrayOf(PropTypes.number),
55
- gridStep: PropTypes.arrayOf(PropTypes.number),
56
- snapStep: PropTypes.arrayOf(PropTypes.number),
57
- markings: PropTypes.string,
58
- backgroundImage: PropTypes.shape({
59
- url: PropTypes.string,
60
- }),
61
- showProtractor: PropTypes.bool,
62
- showRuler: PropTypes.bool,
63
- rulerLabel: PropTypes.string,
64
- rulerTicks: PropTypes.number,
65
- onGraphieUpdated: PropTypes.func,
66
- instructions: PropTypes.string,
67
- onClick: PropTypes.func,
68
- setDrawingAreaAvailable: PropTypes.func,
69
- isMobile: PropTypes.bool,
70
- };
71
-
72
- static defaultProps: any = {
90
+ static defaultProps: DefaultProps = {
73
91
  labels: ["x", "y"],
74
92
  range: [
75
93
  [-10, 10],
@@ -84,67 +102,13 @@ class Graph extends React.Component<any> {
84
102
  showRuler: false,
85
103
  rulerLabel: "",
86
104
  rulerTicks: 10,
87
- instructions: null,
88
- onGraphieUpdated: null,
89
- onClick: null,
90
- onMouseDown: null,
91
105
  isMobile: false,
92
106
  };
93
107
 
94
- render(): React.ReactNode {
95
- let image;
96
- const imageData = this.props.backgroundImage;
97
- if (imageData.url) {
98
- const scale = this.props.box[0] / interactiveSizes.defaultBoxSize;
99
- image = (
100
- // @ts-expect-error [FEI-5003] - TS2741 - Property 'alt' is missing in type '{ src: any; width: any; height: any; scale: number; responsive: false; }' but required in type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "children" | "height" | "width" | "title" | "alt" | "trackInteraction" | "preloader" | "allowFullBleed" | "extraGraphie" | "overrideAriaHidden">'.
101
- <SvgImage
102
- src={imageData.url}
103
- width={imageData.width}
104
- height={imageData.height}
105
- scale={scale}
106
- responsive={false}
107
- />
108
- );
109
- } else {
110
- image = null;
111
- }
112
-
113
- return (
114
- <div
115
- className="graphie-container above-scratchpad"
116
- style={{
117
- width: this.props.box[0],
118
- height: this.props.box[1],
119
- }}
120
- // @ts-expect-error [FEI-5003] - TS2339 - Property 'onMouseOut' does not exist on type 'Graph'.
121
- onMouseOut={this.onMouseOut}
122
- // @ts-expect-error [FEI-5003] - TS2339 - Property 'onMouseOver' does not exist on type 'Graph'.
123
- onMouseOver={this.onMouseOver}
124
- // @ts-expect-error [FEI-5003] - TS2339 - Property 'onClick' does not exist on type 'Graph'.
125
- onClick={this.onClick}
126
- >
127
- {image}
128
- {/* eslint-disable-next-line react/no-string-refs */}
129
- <div className="graphie" ref="graphieDiv" />
130
- </div>
131
- );
132
- }
133
-
134
108
  componentDidMount() {
135
109
  this._setupGraphie(true);
136
110
  }
137
111
 
138
- componentDidUpdate() {
139
- // Only setupGraphie once per componentDidUpdate().
140
- // See explanation in setupGraphie().
141
- this._hasSetupGraphieThisUpdate = false;
142
- if (this._shouldSetupGraphie) {
143
- this._setupGraphie(false);
144
- this._shouldSetupGraphie = false;
145
- }
146
- }
147
-
148
112
  UNSAFE_componentWillReceiveProps(nextProps: any) {
149
113
  const potentialChanges = [
150
114
  "labels",
@@ -166,6 +130,16 @@ class Graph extends React.Component<any> {
166
130
  });
167
131
  }
168
132
 
133
+ componentDidUpdate() {
134
+ // Only setupGraphie once per componentDidUpdate().
135
+ // See explanation in setupGraphie().
136
+ this._hasSetupGraphieThisUpdate = false;
137
+ if (this._shouldSetupGraphie) {
138
+ this._setupGraphie(false);
139
+ this._shouldSetupGraphie = false;
140
+ }
141
+ }
142
+
169
143
  /* Reset the graphie canvas to its initial state
170
144
  *
171
145
  * Use when re-rendering the parent component and you need a blank
@@ -412,6 +386,46 @@ class Graph extends React.Component<any> {
412
386
  "snapStep",
413
387
  );
414
388
  };
389
+
390
+ render(): React.ReactNode {
391
+ let image;
392
+ const imageData = this.props.backgroundImage;
393
+ if (imageData.url) {
394
+ const scale = this.props.box[0] / interactiveSizes.defaultBoxSize;
395
+ image = (
396
+ // @ts-expect-error [FEI-5003] - TS2741 - Property 'alt' is missing in type '{ src: any; width: any; height: any; scale: number; responsive: false; }' but required in type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "children" | "height" | "width" | "title" | "alt" | "trackInteraction" | "preloader" | "allowFullBleed" | "extraGraphie" | "overrideAriaHidden">'.
397
+ <SvgImage
398
+ src={imageData.url}
399
+ width={imageData.width}
400
+ height={imageData.height}
401
+ scale={scale}
402
+ responsive={false}
403
+ />
404
+ );
405
+ } else {
406
+ image = null;
407
+ }
408
+
409
+ return (
410
+ <div
411
+ className="graphie-container above-scratchpad"
412
+ style={{
413
+ width: this.props.box[0],
414
+ height: this.props.box[1],
415
+ }}
416
+ // @ts-expect-error [FEI-5003] - TS2339 - Property 'onMouseOut' does not exist on type 'Graph'.
417
+ onMouseOut={this.onMouseOut}
418
+ // @ts-expect-error [FEI-5003] - TS2339 - Property 'onMouseOver' does not exist on type 'Graph'.
419
+ onMouseOver={this.onMouseOver}
420
+ // @ts-expect-error [FEI-5003] - TS2339 - Property 'onClick' does not exist on type 'Graph'.
421
+ onClick={this.onClick}
422
+ >
423
+ {image}
424
+ {/* eslint-disable-next-line react/no-string-refs */}
425
+ <div className="graphie" ref="graphieDiv" />
426
+ </div>
427
+ );
428
+ }
415
429
  }
416
430
 
417
431
  export default Graph;
@@ -1,5 +1,4 @@
1
1
  import $ from "jquery";
2
- import PropTypes from "prop-types";
3
2
  import * as React from "react";
4
3
  import ReactDOM from "react-dom";
5
4
  import _ from "underscore";
@@ -12,34 +11,58 @@ import GraphUtils from "../util/graph-utils";
12
11
  import GraphieClasses from "./graphie-classes";
13
12
  import Movables from "./graphie-movables";
14
13
 
14
+ import type {Coord} from "../interactive2/types";
15
+ import type {Range, Size} from "../perseus-types";
16
+
15
17
  const GraphieMovable = GraphieClasses.GraphieMovable;
16
18
 
17
19
  const createGraphie = GraphUtils.createGraphie;
18
20
  const {deepEq, nestedMap} = Util;
19
21
  const {assert} = InteractiveUtil;
20
22
 
21
- type Props = any;
23
+ type Props = {
24
+ addMouseLayer?: boolean;
25
+ box: Size;
26
+ range: [Coord, Coord];
27
+ ranges?: [Range, Range];
28
+ gridStep?: [number, number];
29
+ step?: [number, number];
30
+ scale?: [number, number];
31
+
32
+ isMobile?: boolean;
33
+ responsive?: boolean;
34
+
35
+ children?: React.ReactNode;
36
+
37
+ // TODO(LC-772) - type this prop!
38
+ options: any;
39
+
40
+ setDrawingAreaAvailable?: (boolean) => void;
41
+ setup: (
42
+ graphie: any,
43
+ options: {
44
+ range: [Coord, Coord];
45
+ scale: [number, number];
46
+ },
47
+ ) => void;
48
+
49
+ onClick?: (at: Coord) => void;
50
+ onMouseDown?: (at: Coord) => void;
51
+ onMouseMove?: (at: Coord) => void;
52
+ onMouseUp?: (at: Coord) => void;
53
+ };
54
+
55
+ type DefaultProps = {
56
+ range: Props["range"];
57
+ options: Props["options"];
58
+ responsive: Props["responsive"];
59
+ addMouseLayer: Props["addMouseLayer"];
60
+ };
22
61
 
23
62
  class Graphie extends React.Component<Props> {
24
- static propTypes = {
25
- addMouseLayer: PropTypes.bool,
26
- box: PropTypes.arrayOf(PropTypes.number).isRequired,
27
- children: PropTypes.node,
28
- isMobile: PropTypes.bool,
29
- onClick: PropTypes.func,
30
- onMouseDown: PropTypes.func,
31
- onMouseMove: PropTypes.func,
32
- onMouseUp: PropTypes.func,
33
- options: PropTypes.shape({
34
- snapStep: PropTypes.arrayOf(PropTypes.number),
35
- }),
36
- range: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)),
37
- responsive: PropTypes.bool,
38
- setDrawingAreaAvailable: PropTypes.func,
39
- setup: PropTypes.func.isRequired,
40
- };
63
+ graphieDivRef = React.createRef<HTMLDivElement>();
41
64
 
42
- static defaultProps: any = {
65
+ static defaultProps: DefaultProps = {
43
66
  range: [
44
67
  [-10, 10],
45
68
  [-10, 10],
@@ -102,21 +125,30 @@ class Graphie extends React.Component<Props> {
102
125
  };
103
126
 
104
127
  // bounds-checked range
105
- _range: () => ReadonlyArray<[number, number]> = () => {
106
- return _.map(this.props.range, (dimRange) => {
107
- if (dimRange[0] >= dimRange[1]) {
128
+ _range: () => [Coord, Coord] = () => {
129
+ const boundsCheckRange = (range: Coord): Coord => {
130
+ if (range[0] >= range[1]) {
108
131
  return [-10, 10];
109
132
  }
110
- return dimRange;
111
- });
133
+ return range;
134
+ };
135
+ return [
136
+ boundsCheckRange(this.props.range[0]),
137
+ boundsCheckRange(this.props.range[1]),
138
+ ];
112
139
  };
113
140
 
114
- _box: () => ReadonlyArray<number> = () => {
115
- return _.map(this.props.box, (pixelDim) => {
141
+ _box: () => Size = () => {
142
+ const ensureMinSize = (pixelDim: number): number => {
116
143
  // 340 = default size in the editor. exact value
117
144
  // is arbitrary; this is just a safety check.
118
145
  return pixelDim > 0 ? pixelDim : 340;
119
- });
146
+ };
147
+
148
+ return [
149
+ ensureMinSize(this.props.box[0]),
150
+ ensureMinSize(this.props.box[1]),
151
+ ];
120
152
  };
121
153
 
122
154
  _scale: () => ReadonlyArray<number> = () => {
@@ -131,8 +163,7 @@ class Graphie extends React.Component<Props> {
131
163
  _setupGraphie: () => void = () => {
132
164
  this._removeMovables();
133
165
 
134
- // eslint-disable-next-line react/no-string-refs
135
- const graphieDiv = ReactDOM.findDOMNode(this.refs.graphieDiv);
166
+ const graphieDiv = ReactDOM.findDOMNode(this.graphieDivRef.current);
136
167
  // @ts-expect-error [FEI-5003] - TS2769 - No overload matches this call. | TS2339 - Property 'empty' does not exist on type 'JQueryStatic'.
137
168
  $(graphieDiv).empty();
138
169
  // @ts-expect-error [FEI-5003] - TS2339 - Property '_graphie' does not exist on type 'Graphie'.
@@ -342,8 +373,7 @@ class Graphie extends React.Component<Props> {
342
373
  render(): React.ReactNode {
343
374
  return (
344
375
  <div className="graphie-container">
345
- {/* eslint-disable-next-line react/no-string-refs */}
346
- <div className="graphie" ref="graphieDiv" />
376
+ <div className="graphie" ref={this.graphieDivRef} />
347
377
  </div>
348
378
  );
349
379
  }
@@ -31,7 +31,7 @@ import type {
31
31
  DOMRange,
32
32
  } from "./types";
33
33
 
34
- type HighlightableContentProps = {
34
+ type Props = {
35
35
  // The highlightable content itself. Highlights will be defined relative to
36
36
  // the content specified here.
37
37
  children?: React.ReactElement<any>;
@@ -57,21 +57,18 @@ type HighlightableContentProps = {
57
57
  serializedHighlights: SerializedHighlightSet;
58
58
  };
59
59
 
60
- type HighlightableContentState = {
60
+ type State = {
61
61
  // A cached list of DOMRanges, each representing one of the content's
62
62
  // semantic words. Sorted in document order.
63
63
  wordRanges: ReadonlyArray<DOMRange>;
64
64
  };
65
65
 
66
- class HighlightableContent extends React.PureComponent<
67
- HighlightableContentProps,
68
- HighlightableContentState
69
- > {
66
+ class HighlightableContent extends React.PureComponent<Props, State> {
70
67
  // References to the mounted container and content divs.
71
68
  _container: HTMLElement | null | undefined;
72
69
  _content: HTMLElement | null | undefined;
73
70
 
74
- state: HighlightableContentState = {
71
+ state: State = {
75
72
  wordRanges: [],
76
73
  };
77
74
 
@@ -21,7 +21,7 @@ import {
21
21
 
22
22
  import type {DOMHighlight, Position, Rect, ZIndexes} from "./types";
23
23
 
24
- type HighlightRendererProps = {
24
+ type Props = {
25
25
  // The DOMHighlight to render.
26
26
  highlight: DOMHighlight;
27
27
  // A unique key corresponding to the given `highlight`.
@@ -36,7 +36,7 @@ type HighlightRendererProps = {
36
36
  zIndexes: ZIndexes;
37
37
  };
38
38
 
39
- type HighlightRendererState = {
39
+ type State = {
40
40
  // The set of rectangles that cover this highlight's content, relative to
41
41
  // the offset parent. This cache is updated on mount and on changes to
42
42
  // the `highlight` and `offsetParent` props.
@@ -50,17 +50,14 @@ type HighlightRendererState = {
50
50
  cachedHighlightRects: ReadonlyArray<Rect>;
51
51
  };
52
52
 
53
- class HighlightRenderer extends React.PureComponent<
54
- HighlightRendererProps,
55
- HighlightRendererState
56
- > {
57
- state: HighlightRendererState = {
53
+ class HighlightRenderer extends React.PureComponent<Props, State> {
54
+ state: State = {
58
55
  cachedHighlightRects: this._computeRects(this.props),
59
56
  // @ts-expect-error [FEI-5003] - TS2322 - Type '{ cachedHighlightRects: readonly Rect[]; tooltipIsHovered: boolean; }' is not assignable to type 'HighlightRendererState'.
60
57
  tooltipIsHovered: false,
61
58
  };
62
59
 
63
- UNSAFE_componentWillReceiveProps(nextProps: HighlightRendererProps) {
60
+ UNSAFE_componentWillReceiveProps(nextProps: Props) {
64
61
  if (
65
62
  this.props.highlight !== nextProps.highlight ||
66
63
  this.props.offsetParent !== nextProps.offsetParent
@@ -76,7 +73,7 @@ class HighlightRenderer extends React.PureComponent<
76
73
  * coordinates relative to the offset parent. That way, we can use them
77
74
  * for CSS positioning.
78
75
  */
79
- _computeRects(props: HighlightRendererProps): ReadonlyArray<Rect> {
76
+ _computeRects(props: Props): ReadonlyArray<Rect> {
80
77
  const {highlight, offsetParent} = props;
81
78
 
82
79
  // Get the set of rectangles that covers the range's text, relative to
@@ -15,7 +15,7 @@ import HighlightTooltip from "./highlight-tooltip";
15
15
 
16
16
  import type {DOMHighlightSet, Position, ZIndexes} from "./types";
17
17
 
18
- type HighlightSetRendererProps = {
18
+ type Props = {
19
19
  // Whether the highlights are user-editable. If false, highlights are
20
20
  // read-only.
21
21
  editable: boolean;
@@ -33,7 +33,7 @@ type HighlightSetRendererProps = {
33
33
  // highlights below content.
34
34
  zIndexes: ZIndexes;
35
35
  };
36
- type HighlightSetRendererState = {
36
+ type State = {
37
37
  // If the user is currently hovering over a highlight, this field contains
38
38
  // its key.
39
39
  hoveredHighlightKey: string | null | undefined;
@@ -42,11 +42,8 @@ type HighlightSetRendererState = {
42
42
  hoveringTooltipFor: string | null | undefined;
43
43
  };
44
44
 
45
- class HighlightSetRenderer extends React.PureComponent<
46
- HighlightSetRendererProps,
47
- HighlightSetRendererState
48
- > {
49
- state: HighlightSetRendererState = {
45
+ class HighlightSetRenderer extends React.PureComponent<Props, State> {
46
+ state: State = {
50
47
  hoveredHighlightKey: null,
51
48
  hoveringTooltipFor: null,
52
49
  };
@@ -60,7 +57,7 @@ class HighlightSetRenderer extends React.PureComponent<
60
57
  this._updateEditListeners(false, this.props.editable);
61
58
  }
62
59
 
63
- UNSAFE_componentWillReceiveProps(nextProps: HighlightSetRendererProps) {
60
+ UNSAFE_componentWillReceiveProps(nextProps: Props) {
64
61
  this._updateEditListeners(this.props.editable, nextProps.editable);
65
62
 
66
63
  // If we were previously hovering over a highlight that has been
@@ -23,7 +23,7 @@ import {getRelativeRect} from "./util";
23
23
 
24
24
  import type {Rect} from "./types";
25
25
 
26
- type HighlightTooltipProps = {
26
+ type Props = {
27
27
  label: string;
28
28
  onClick: () => unknown;
29
29
  onMouseEnter?: () => unknown;
@@ -33,7 +33,7 @@ type HighlightTooltipProps = {
33
33
  offsetParent: Element;
34
34
  };
35
35
 
36
- class HighlightTooltip extends React.PureComponent<HighlightTooltipProps> {
36
+ class HighlightTooltip extends React.PureComponent<Props> {
37
37
  _getFocusRect(): Rect | null | undefined {
38
38
  const {focusNode, focusOffset, offsetParent} = this.props;
39
39
 
@@ -21,7 +21,7 @@ import SelectionTracker from "./selection-tracker";
21
21
  import type {TrackedSelection} from "./selection-tracker";
22
22
  import type {DOMHighlight, DOMHighlightSet, DOMRange, ZIndexes} from "./types";
23
23
 
24
- type HighlightingUIProps = {
24
+ type Props = {
25
25
  // A function that builds a DOMHighlight from the given DOMRange, if
26
26
  // possible. If it would not currently be valid to add a highlight over the
27
27
  // given DOMRange, returns null.
@@ -49,7 +49,7 @@ type HighlightingUIProps = {
49
49
  zIndexes: ZIndexes;
50
50
  };
51
51
 
52
- class HighlightingUI extends React.PureComponent<HighlightingUIProps> {
52
+ class HighlightingUI extends React.PureComponent<Props> {
53
53
  _handleAddHighlight(highlightToAdd: DOMHighlight) {
54
54
  this.props.onAddHighlight(highlightToAdd);
55
55