@khanacademy/perseus 5.0.0 → 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 (113) hide show
  1. package/CHANGELOG.md +42 -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/hud.d.ts +8 -14
  9. package/dist/components/hud.js.flow +7 -14
  10. package/dist/components/inline-icon.d.ts +9 -19
  11. package/dist/components/inline-icon.js.flow +26 -13
  12. package/dist/components/lint.d.ts +41 -13
  13. package/dist/components/lint.js.flow +42 -13
  14. package/dist/components/math-output.d.ts +15 -11
  15. package/dist/components/math-output.js.flow +15 -11
  16. package/dist/components/sortable.d.ts +17 -9
  17. package/dist/components/sortable.js.flow +22 -9
  18. package/dist/components/svg-image.d.ts +5 -3
  19. package/dist/components/svg-image.js.flow +5 -3
  20. package/dist/components/tooltip.d.ts +45 -4
  21. package/dist/components/tooltip.js.flow +44 -31
  22. package/dist/es/index.css +0 -3
  23. package/dist/es/index.js +477 -648
  24. package/dist/es/index.js.map +1 -1
  25. package/dist/index.css +0 -3
  26. package/dist/index.js +481 -645
  27. package/dist/index.js.map +1 -1
  28. package/dist/perseus-types.d.ts +11 -9
  29. package/dist/perseus-types.js.flow +11 -9
  30. package/dist/renderer.d.ts +2 -2
  31. package/dist/renderer.js.flow +1 -3
  32. package/dist/styles/shared.d.ts +0 -1
  33. package/dist/styles/shared.js.flow +0 -1
  34. package/dist/types.d.ts +0 -10
  35. package/dist/types.js.flow +0 -13
  36. package/dist/util/a11y.d.ts +0 -1
  37. package/dist/util/a11y.js.flow +0 -1
  38. package/dist/util/interactive.d.ts +2 -0
  39. package/dist/util/interactive.js.flow +2 -0
  40. package/dist/util.d.ts +3 -3
  41. package/dist/util.js.flow +4 -3
  42. package/dist/widgets/grapher.d.ts +1 -1
  43. package/dist/widgets/grapher.js.flow +12 -3
  44. package/dist/widgets/matcher.d.ts +7 -3
  45. package/dist/widgets/matcher.js.flow +7 -3
  46. package/dist/widgets/number-line.d.ts +1 -1
  47. package/dist/widgets/number-line.js.flow +1 -1
  48. package/package.json +2 -2
  49. package/src/__tests__/__snapshots__/item-renderer.test.tsx.snap +151 -159
  50. package/src/__tests__/__snapshots__/renderer.test.tsx.snap +358 -394
  51. package/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap +169 -189
  52. package/src/components/__stories__/lint.stories.tsx +56 -21
  53. package/src/components/__stories__/sortable.stories.tsx +5 -5
  54. package/src/components/__stories__/tooltip.stories.tsx +52 -0
  55. package/src/components/__tests__/__snapshots__/sortable.test.tsx.snap +114 -30
  56. package/src/components/__tests__/__snapshots__/sorter.test.tsx.snap +172 -204
  57. package/src/components/__tests__/sortable.test.tsx +54 -16
  58. package/src/components/__tests__/sorter.test.tsx +12 -9
  59. package/src/components/fixed-to-responsive.tsx +43 -38
  60. package/src/components/graph.tsx +95 -81
  61. package/src/components/graphie.tsx +62 -32
  62. package/src/components/hud.tsx +104 -115
  63. package/src/components/inline-icon.tsx +15 -32
  64. package/src/components/input-with-examples.tsx +4 -4
  65. package/src/components/lint.tsx +47 -41
  66. package/src/components/math-output.tsx +17 -11
  67. package/src/components/simple-keypad-input.tsx +2 -2
  68. package/src/components/sortable.tsx +134 -94
  69. package/src/components/svg-image.tsx +10 -11
  70. package/src/components/tooltip.tsx +189 -171
  71. package/src/interactive2/types.ts +2 -2
  72. package/src/multi-items/__tests__/__snapshots__/multi-renderer.test.tsx.snap +708 -764
  73. package/src/perseus-types.ts +13 -9
  74. package/src/renderer.tsx +11 -22
  75. package/src/types.ts +0 -18
  76. package/src/util/interactive.ts +18 -5
  77. package/src/util/tex.ts +13 -77
  78. package/src/util.ts +3 -4
  79. package/src/widgets/__tests__/__snapshots__/categorizer.test.ts.snap +717 -773
  80. package/src/widgets/__tests__/__snapshots__/cs-program.test.ts.snap +28 -36
  81. package/src/widgets/__tests__/__snapshots__/definition.test.ts.snap +52 -60
  82. package/src/widgets/__tests__/__snapshots__/dropdown.test.ts.snap +100 -108
  83. package/src/widgets/__tests__/__snapshots__/explanation.test.ts.snap +212 -260
  84. package/src/widgets/__tests__/__snapshots__/graded-group-set-jipt.test.ts.snap +613 -641
  85. package/src/widgets/__tests__/__snapshots__/graded-group-set.test.ts.snap +249 -261
  86. package/src/widgets/__tests__/__snapshots__/graded-group.test.ts.snap +671 -735
  87. package/src/widgets/__tests__/__snapshots__/grapher.test.ts.snap +2676 -2684
  88. package/src/widgets/__tests__/__snapshots__/group.test.tsx.snap +938 -1002
  89. package/src/widgets/__tests__/__snapshots__/iframe.test.ts.snap +28 -36
  90. package/src/widgets/__tests__/__snapshots__/image.test.ts.snap +227 -255
  91. package/src/widgets/__tests__/__snapshots__/input-number.test.ts.snap +353 -357
  92. package/src/widgets/__tests__/__snapshots__/interaction.test.ts.snap +255 -259
  93. package/src/widgets/__tests__/__snapshots__/interactive-graph.test.ts.snap +2401 -2433
  94. package/src/widgets/__tests__/__snapshots__/matcher.test.tsx.snap +600 -756
  95. package/src/widgets/__tests__/__snapshots__/matrix.test.ts.snap +420 -428
  96. package/src/widgets/__tests__/__snapshots__/number-line.test.ts.snap +762 -770
  97. package/src/widgets/__tests__/__snapshots__/numeric-input.test.ts.snap +373 -393
  98. package/src/widgets/__tests__/__snapshots__/orderer.test.ts.snap +116 -148
  99. package/src/widgets/__tests__/__snapshots__/passage-ref.test.ts.snap +289 -301
  100. package/src/widgets/__tests__/__snapshots__/passage.test.tsx.snap +1679 -1711
  101. package/src/widgets/__tests__/__snapshots__/radio.test.ts.snap +2692 -2960
  102. package/src/widgets/__tests__/__snapshots__/video.test.ts.snap +90 -98
  103. package/src/widgets/__tests__/matcher.test.tsx +33 -9
  104. package/src/widgets/expression.tsx +9 -6
  105. package/src/widgets/grapher.tsx +3 -3
  106. package/src/widgets/image.tsx +2 -2
  107. package/src/widgets/interactive-graph.tsx +5 -5
  108. package/src/widgets/matcher.tsx +43 -24
  109. package/src/widgets/number-line.tsx +1 -1
  110. package/src/widgets/simulator.tsx +4 -6
  111. package/{tsconfig.json → tsconfig-build.json} +6 -6
  112. package/tsconfig-build.tsbuildinfo +1 -0
  113. package/tsconfig.tsbuildinfo +0 -1
@@ -1,3 +1,4 @@
1
+ /* eslint-disable react/no-unsafe */
1
2
  /**
2
3
  * A generic tooltip library for React.js
3
4
  *
@@ -7,9 +8,9 @@
7
8
  * import Tooltip from "./tooltip";
8
9
  * <Tooltip
9
10
  * className="class-for-tooltip-contents"
10
- * horizontalPosition="left" // one of "left", "right"
11
- * horizontalAlign="left" // one of "left", "right"
12
- * verticalPosition="bottom" // one of "top", "bottom"
11
+ * horizontalPosition={HoriziontalDirection.Left}
12
+ * horizontalAlign={HoriziontalDirection.Left}
13
+ * verticalPosition={VerticalDirection.Top}
13
14
  * arrowSize={10} // arrow size in pixels
14
15
  * borderColor="#ccc" // color of the border for the tooltip
15
16
  * show={true} // whether the tooltip should currently be visible
@@ -40,136 +41,142 @@
40
41
  // TODO(joel/aria) fix z-index issues https://s3.amazonaws.com/uploads.hipchat.com/6574/29028/yOApjwmgiMhEZYJ/Screen%20Shot%202014-05-30%20at%203.34.18%20PM.png
41
42
  // z-index: 3 on perseus-formats-tooltip seemed to work
42
43
 
43
- import createReactClass from "create-react-class";
44
- import PropTypes from "prop-types";
45
44
  import * as React from "react";
46
45
  import ReactDOM from "react-dom";
47
46
 
48
- const zIndex = 10;
49
-
50
- const Triangle = createReactClass({
51
- propTypes: {
52
- color: PropTypes.string.isRequired,
53
- left: PropTypes.number.isRequired,
54
- top: PropTypes.number.isRequired,
55
- width: PropTypes.number.isRequired,
56
- height: PropTypes.number.isRequired,
57
- horizontalDirection: PropTypes.oneOf(["left", "right"]).isRequired,
58
- verticalDirection: PropTypes.oneOf(["top", "bottom"]).isRequired,
59
- },
60
-
61
- render: function () {
62
- let borderLeft;
63
- let borderRight;
64
- let borderTop;
65
- let borderBottom;
66
-
67
- const hBorder = `${this.props.width}px solid transparent`;
68
- if (this.props.horizontalDirection === "right") {
69
- borderLeft = hBorder;
70
- } else {
71
- borderRight = hBorder;
72
- }
73
-
74
- const vBorder = `${this.props.height}px solid ${this.props.color}`;
75
- if (this.props.verticalDirection === "top") {
76
- borderTop = vBorder;
77
- } else {
78
- borderBottom = vBorder;
79
- }
80
-
81
- return (
82
- <div
83
- style={{
84
- display: "block",
85
- height: 0,
86
- width: 0,
87
- position: "absolute",
88
- left: this.props.left,
89
- top: this.props["top"],
90
- borderLeft: borderLeft,
91
- borderRight: borderRight,
92
- borderTop: borderTop,
93
- borderBottom: borderBottom,
94
- }}
95
- />
96
- );
97
- },
98
- });
99
-
100
- const TooltipArrow = createReactClass({
101
- propTypes: {
102
- position: PropTypes.string,
103
- visibility: PropTypes.string,
104
- left: PropTypes.number,
105
- top: PropTypes.number,
106
- color: PropTypes.string.isRequired, // a css color
107
- border: PropTypes.string.isRequired, // a css color
108
- width: PropTypes.number.isRequired,
109
- height: PropTypes.number.isRequired,
110
- horizontalDirection: PropTypes.oneOf(["left", "right"]).isRequired,
111
- verticalDirection: PropTypes.oneOf(["top", "bottom"]).isRequired,
112
- },
47
+ import type {Property} from "csstype";
113
48
 
114
- getDefaultProps: function () {
115
- return {
116
- position: "relative",
117
- visibility: "visible",
118
- left: 0,
119
- top: 0,
120
- };
121
- },
49
+ const zIndex = 10;
122
50
 
51
+ export enum HorizontalDirection {
52
+ Left = "left",
53
+ Right = "right",
54
+ }
55
+
56
+ export enum VerticalDirection {
57
+ Top = "top",
58
+ Bottom = "bottom",
59
+ }
60
+
61
+ type TriangleProps = {
62
+ color: string;
63
+ left: number;
64
+ top: number;
65
+ width: number;
66
+ height: number;
67
+ horizontalDirection: HorizontalDirection;
68
+ verticalDirection: VerticalDirection;
69
+ };
70
+
71
+ const Triangle = (props: TriangleProps) => {
72
+ let borderLeft;
73
+ let borderRight;
74
+ let borderTop;
75
+ let borderBottom;
76
+
77
+ const hBorder = `${props.width}px solid transparent`;
78
+ if (props.horizontalDirection === "right") {
79
+ borderLeft = hBorder;
80
+ } else {
81
+ borderRight = hBorder;
82
+ }
83
+
84
+ const vBorder = `${props.height}px solid ${props.color}`;
85
+ if (props.verticalDirection === "top") {
86
+ borderTop = vBorder;
87
+ } else {
88
+ borderBottom = vBorder;
89
+ }
90
+
91
+ return (
92
+ <div
93
+ style={{
94
+ display: "block",
95
+ height: 0,
96
+ width: 0,
97
+ position: "absolute",
98
+ left: props.left,
99
+ top: props["top"],
100
+ borderLeft: borderLeft,
101
+ borderRight: borderRight,
102
+ borderTop: borderTop,
103
+ borderBottom: borderBottom,
104
+ }}
105
+ />
106
+ );
107
+ };
108
+
109
+ type TooltipArrowProps = {
110
+ position: Property.Position;
111
+ visibility: Property.Visibility;
112
+ left: number;
113
+ top: number;
114
+ color: string; // a css color
115
+ border: string; // a css color
116
+ width: number;
117
+ height: number;
118
+ horizontalDirection: HorizontalDirection;
119
+ verticalDirection: VerticalDirection;
120
+ zIndex?: number;
121
+ };
122
+
123
+ const TooltipArrow = (props: TooltipArrowProps) => {
123
124
  // TODO(aria): Think about adding a box-shadow to the triangle here
124
125
  // See http://css-tricks.com/triangle-with-shadow/
125
- render: function () {
126
- //const isRight = (this.props.horizontalDirection === "right");
127
- const isTop = this.props.verticalDirection === "top";
128
-
129
- const frontTopOffset = isTop ? 0 : 1;
130
- const borderTopOffset = isTop ? 0 : -1;
131
126
 
132
- return (
133
- <div
134
- style={{
135
- display: "block",
136
- position: this.props.position,
137
- visibility: this.props.visibility,
138
- left: this.props.left,
139
- top: this.props["top"],
140
- width: this.props.width + 2,
141
- height: this.props.height + 1,
142
- marginTop: -1,
143
- marginBottom: -2,
144
- zIndex: zIndex,
145
- }}
146
- >
147
- {/* The background triangle used to create the effect of a
127
+ //const isRight = (this.props.horizontalDirection === "right");
128
+ const isTop = props.verticalDirection === "top";
129
+
130
+ const frontTopOffset = isTop ? 0 : 1;
131
+ const borderTopOffset = isTop ? 0 : -1;
132
+
133
+ return (
134
+ <div
135
+ style={{
136
+ display: "block",
137
+ position: props.position,
138
+ visibility: props.visibility,
139
+ left: props.left,
140
+ top: props["top"],
141
+ width: props.width + 2,
142
+ height: props.height + 1,
143
+ marginTop: -1,
144
+ marginBottom: -2,
145
+ zIndex: zIndex,
146
+ }}
147
+ >
148
+ {/* The background triangle used to create the effect of a
148
149
  border around the foreground triangle*/}
149
- <Triangle
150
- horizontalDirection={this.props.horizontalDirection}
151
- verticalDirection={this.props.verticalDirection}
152
- color={this.props.border}
153
- left={0}
154
- top={borderTopOffset}
155
- width={this.props.width + 2} // one extra for the diagonal
156
- height={this.props.height + 2}
157
- />
158
- {/* The foreground triangle covers all but the left/right edges
150
+ <Triangle
151
+ horizontalDirection={props.horizontalDirection}
152
+ verticalDirection={props.verticalDirection}
153
+ color={props.border}
154
+ left={0}
155
+ top={borderTopOffset}
156
+ width={props.width + 2} // one extra for the diagonal
157
+ height={props.height + 2}
158
+ />
159
+ {/* The foreground triangle covers all but the left/right edges
159
160
  of the background triangle */}
160
- <Triangle
161
- horizontalDirection={this.props.horizontalDirection}
162
- verticalDirection={this.props.verticalDirection}
163
- color={this.props.color}
164
- left={1}
165
- top={frontTopOffset}
166
- width={this.props.width}
167
- height={this.props.height}
168
- />
169
- </div>
170
- );
171
- },
172
- });
161
+ <Triangle
162
+ horizontalDirection={props.horizontalDirection}
163
+ verticalDirection={props.verticalDirection}
164
+ color={props.color}
165
+ left={1}
166
+ top={frontTopOffset}
167
+ width={props.width}
168
+ height={props.height}
169
+ />
170
+ </div>
171
+ );
172
+ };
173
+
174
+ TooltipArrow.defaultProps = {
175
+ position: "relative",
176
+ visibility: "visible",
177
+ left: 0,
178
+ top: 0,
179
+ };
173
180
 
174
181
  const VERTICAL_CORNERS = {
175
182
  top: {
@@ -201,52 +208,61 @@ const HORIZONTAL_ALIGNMNENTS = {
201
208
  },
202
209
  } as const;
203
210
 
204
- // eslint-disable-next-line react/no-unsafe
205
- const Tooltip = createReactClass({
206
- propTypes: {
207
- show: PropTypes.bool.isRequired,
208
- className: PropTypes.string,
209
- arrowSize: PropTypes.number,
210
- borderColor: PropTypes.string,
211
- verticalPosition: PropTypes.oneOf(Object.keys(VERTICAL_CORNERS)),
212
- horizontalPosition: PropTypes.oneOf(Object.keys(HORIZONTAL_CORNERS)),
213
- horizontalAlign: PropTypes.oneOf(Object.keys(HORIZONTAL_ALIGNMNENTS)),
214
- children: PropTypes.arrayOf(PropTypes.element).isRequired,
215
- targetContainerStyle: PropTypes.any, // style object
216
- },
217
-
218
- getDefaultProps: function () {
219
- return {
220
- className: "",
221
- arrowSize: 10,
222
- borderColor: "#ccc",
223
- verticalPosition: "bottom",
224
- horizontalPosition: "left",
225
- horizontalAlign: "left",
226
- targetContainerStyle: {},
227
- };
228
- },
229
-
230
- getInitialState: function () {
231
- return {
232
- height: null, // used for offsetting "top" positioned tooltips
233
- };
234
- },
235
-
236
- componentDidMount: function () {
211
+ type Props = {
212
+ show: boolean;
213
+ className: string;
214
+ arrowSize: number;
215
+ borderColor: string;
216
+ verticalPosition: VerticalDirection;
217
+ horizontalPosition: HorizontalDirection;
218
+ horizontalAlign: HorizontalDirection.Left;
219
+ children: React.ReactNode;
220
+ targetContainerStyle: any; // style object
221
+ };
222
+
223
+ type DefaultProps = {
224
+ className: Props["className"];
225
+ arrowSize: Props["arrowSize"];
226
+ borderColor: Props["borderColor"];
227
+ verticalPosition: Props["verticalPosition"];
228
+ horizontalPosition: Props["horizontalPosition"];
229
+ horizontalAlign: Props["horizontalAlign"];
230
+ targetContainerStyle: Props["targetContainerStyle"];
231
+ };
232
+
233
+ type State = {
234
+ height: number | null;
235
+ };
236
+
237
+ class Tooltip extends React.Component<Props, State> {
238
+ static defaultProps: DefaultProps = {
239
+ className: "",
240
+ arrowSize: 10,
241
+ borderColor: "#ccc",
242
+ verticalPosition: VerticalDirection.Bottom,
243
+ horizontalPosition: HorizontalDirection.Left,
244
+ horizontalAlign: HorizontalDirection.Left,
245
+ targetContainerStyle: {},
246
+ };
247
+
248
+ state: State = {
249
+ height: null, // used for offsetting "top" positioned tooltips
250
+ };
251
+
252
+ componentDidMount() {
237
253
  this._updateHeight();
238
- },
254
+ }
239
255
 
240
- UNSAFE_componentWillReceiveProps: function () {
256
+ UNSAFE_componentWillReceiveProps() {
241
257
  // If the contents have changed, reset our measure of the height
242
258
  this.setState({height: null});
243
- },
259
+ }
244
260
 
245
- componentDidUpdate: function () {
261
+ componentDidUpdate() {
246
262
  this._updateHeight();
247
- },
263
+ }
248
264
 
249
- _renderToolTipDiv: function (isTooltipAbove) {
265
+ _renderToolTipDiv(isTooltipAbove?: boolean) {
250
266
  const settings = Object.assign(
251
267
  {},
252
268
  HORIZONTAL_CORNERS[this.props.horizontalPosition],
@@ -261,7 +277,7 @@ const Tooltip = createReactClass({
261
277
  // We put an absolutely positioned arrow in the correct place
262
278
  arrowAbove = (
263
279
  <TooltipArrow
264
- verticalDirection="top"
280
+ verticalDirection={VerticalDirection.Top}
265
281
  horizontalDirection={this.props.horizontalAlign}
266
282
  position="absolute"
267
283
  color="white"
@@ -278,7 +294,7 @@ const Tooltip = createReactClass({
278
294
  // content by the correct amount
279
295
  arrowBelow = (
280
296
  <TooltipArrow
281
- verticalDirection="top"
297
+ verticalDirection={VerticalDirection.Top}
282
298
  horizontalDirection={this.props.horizontalAlign}
283
299
  visibility="hidden"
284
300
  color="white"
@@ -293,7 +309,7 @@ const Tooltip = createReactClass({
293
309
  } else {
294
310
  arrowAbove = (
295
311
  <TooltipArrow
296
- verticalDirection="bottom"
312
+ verticalDirection={VerticalDirection.Bottom}
297
313
  horizontalDirection={this.props.horizontalAlign}
298
314
  color="white"
299
315
  border={this.props.borderColor}
@@ -348,6 +364,7 @@ const Tooltip = createReactClass({
348
364
  zIndex: zIndex - 1,
349
365
  }}
350
366
  >
367
+ {/* @ts-expect-error TS2533 - First child is target, rest is tooltip content */}
351
368
  {this.props.children.slice(1)}
352
369
  </div>
353
370
 
@@ -355,9 +372,9 @@ const Tooltip = createReactClass({
355
372
  </div>
356
373
  </div>
357
374
  );
358
- },
375
+ }
359
376
 
360
- _updateHeight: function () {
377
+ _updateHeight() {
361
378
  const tooltipContainer = ReactDOM.findDOMNode(
362
379
  // eslint-disable-next-line react/no-string-refs
363
380
  this.refs.tooltipContainer,
@@ -366,9 +383,9 @@ const Tooltip = createReactClass({
366
383
  if (height !== this.state.height) {
367
384
  this.setState({height});
368
385
  }
369
- },
386
+ }
370
387
 
371
- render: function () {
388
+ render() {
372
389
  const isTooltipAbove = this.props.verticalPosition === "top";
373
390
 
374
391
  /* We wrap the entire output in a span so that it displays inline */
@@ -379,14 +396,15 @@ const Tooltip = createReactClass({
379
396
  {/* We wrap our input in a div so that we can put the tooltip in a
380
397
  div above/below it */}
381
398
  <div style={this.props.targetContainerStyle}>
399
+ {/* @ts-expect-error TS2533 - First child is target, rest is tooltip content */}
382
400
  {this.props.children[0]}
383
401
  </div>
384
402
 
385
403
  {!isTooltipAbove && this._renderToolTipDiv()}
386
404
  </span>
387
405
  );
388
- },
389
- });
406
+ }
407
+ }
390
408
 
391
409
  // Sorry. // Apology-Oriented-Programming
392
410
  export default Tooltip;
@@ -1,2 +1,2 @@
1
- export type Coord = [number, number];
2
- export type Line = [Coord, Coord];
1
+ export type Coord = [number, number]; // x, y
2
+ export type Line = [Coord, Coord]; // start, end