@khanacademy/wonder-blocks-tooltip 1.3.3 → 1.3.7

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/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # @khanacademy/wonder-blocks-tooltip
2
+
3
+ ## 1.3.7
4
+
5
+ ### Patch Changes
6
+
7
+ - @khanacademy/wonder-blocks-core@4.2.1
8
+ - @khanacademy/wonder-blocks-layout@1.4.7
9
+ - @khanacademy/wonder-blocks-modal@2.2.1
10
+ - @khanacademy/wonder-blocks-typography@1.1.29
11
+
12
+ ## 1.3.6
13
+
14
+ ### Patch Changes
15
+
16
+ - Updated dependencies [e7bbf149]
17
+ - @khanacademy/wonder-blocks-modal@2.2.0
package/dist/es/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { Component, createElement, cloneElement, Fragment } from 'react';
2
- import { findDOMNode, createPortal } from 'react-dom';
1
+ import * as React from 'react';
2
+ import * as ReactDOM from 'react-dom';
3
3
  import { Text as Text$1, View, UniqueIDProvider } from '@khanacademy/wonder-blocks-core';
4
4
  import { maybeGetPortalMountedModalHostElement } from '@khanacademy/wonder-blocks-modal';
5
- import { css, StyleSheet } from 'aphrodite';
5
+ import { StyleSheet, css } from 'aphrodite';
6
6
  import Colors from '@khanacademy/wonder-blocks-color';
7
7
  import Spacing from '@khanacademy/wonder-blocks-spacing';
8
8
  import _extends from '@babel/runtime/helpers/extends';
@@ -118,7 +118,7 @@ const TooltipDisappearanceDelay = 75;
118
118
  * positioning and displaying tooltips.
119
119
  */
120
120
  const TRACKER = new ActiveTracker();
121
- class TooltipAnchor extends Component {
121
+ class TooltipAnchor extends React.Component {
122
122
  constructor(props) {
123
123
  super(props);
124
124
 
@@ -182,7 +182,7 @@ class TooltipAnchor extends Component {
182
182
  }
183
183
 
184
184
  componentDidMount() {
185
- const anchorNode = findDOMNode(this); // This should never happen, but we have this check here to make flow
185
+ const anchorNode = ReactDOM.findDOMNode(this); // This should never happen, but we have this check here to make flow
186
186
  // happy and ensure that if this does happen, we'll know about it.
187
187
 
188
188
  if (anchorNode instanceof Text) {
@@ -327,13 +327,13 @@ class TooltipAnchor extends Component {
327
327
  const {
328
328
  children
329
329
  } = this.props;
330
- return typeof children === "string" ? /*#__PURE__*/createElement(Text$1, null, children) : children;
330
+ return typeof children === "string" ? /*#__PURE__*/React.createElement(Text$1, null, children) : children;
331
331
  }
332
332
 
333
333
  _renderAccessibleChildren(ids) {
334
334
  const anchorableChildren = this._renderAnchorableChildren();
335
335
 
336
- return /*#__PURE__*/cloneElement(anchorableChildren, {
336
+ return /*#__PURE__*/React.cloneElement(anchorableChildren, {
337
337
  "aria-describedby": ids.get(TooltipAnchor.ariaContentId)
338
338
  });
339
339
  }
@@ -359,7 +359,7 @@ TooltipAnchor.ariaContentId = "aria-content";
359
359
  // TODO(somewhatabstract): Replace this really basic unique ID work with
360
360
  // something SSR-friendly and more robust.
361
361
  let tempIdCounter = 0;
362
- class TooltipTail extends Component {
362
+ class TooltipTail extends React.Component {
363
363
  _calculateDimensionsFromPlacement() {
364
364
  const {
365
365
  placement
@@ -476,7 +476,7 @@ class TooltipTail extends Component {
476
476
  offsetShadowX
477
477
  } = position;
478
478
  const dropShadowFilterId = `tooltip-dropshadow-${placement}-${tempIdCounter++}`;
479
- return [/*#__PURE__*/createElement("filter", {
479
+ return [/*#__PURE__*/React.createElement("filter", {
480
480
  key: "filter",
481
481
  id: dropShadowFilterId // Height and width tell the filter how big of a canvas to
482
482
  // draw based on its parent size. i.e. 2 times bigger.
@@ -491,10 +491,10 @@ class TooltipTail extends Component {
491
491
  ,
492
492
  x: x,
493
493
  y: y
494
- }, /*#__PURE__*/createElement("feGaussianBlur", {
494
+ }, /*#__PURE__*/React.createElement("feGaussianBlur", {
495
495
  in: "SourceAlpha",
496
496
  stdDeviation: Spacing.xxSmall_6 / 2
497
- }), /*#__PURE__*/createElement("feComponentTransfer", null, /*#__PURE__*/createElement("feFuncA", {
497
+ }), /*#__PURE__*/React.createElement("feComponentTransfer", null, /*#__PURE__*/React.createElement("feFuncA", {
498
498
  type: "linear",
499
499
  slope: "0.3"
500
500
  }))),
@@ -512,10 +512,10 @@ class TooltipTail extends Component {
512
512
  *
513
513
  * See styles below for why we offset the arrow.
514
514
  */
515
- createElement("g", {
515
+ React.createElement("g", {
516
516
  key: "dropshadow",
517
517
  transform: `translate(${offsetShadowX},5.5)`
518
- }, /*#__PURE__*/createElement("polyline", {
518
+ }, /*#__PURE__*/React.createElement("polyline", {
519
519
  fill: Colors.offBlack16,
520
520
  points: points.join(" "),
521
521
  stroke: Colors.offBlack32,
@@ -656,23 +656,23 @@ class TooltipTail extends Component {
656
656
  const {
657
657
  color
658
658
  } = this.props;
659
- return /*#__PURE__*/createElement("svg", {
660
- className: css(styles.arrow),
659
+ return /*#__PURE__*/React.createElement("svg", {
660
+ className: css(styles$2.arrow),
661
661
  style: this._getArrowStyle(),
662
662
  width: width,
663
663
  height: height
664
- }, this._maybeRenderDropshadow(points), /*#__PURE__*/createElement("polyline", {
664
+ }, this._maybeRenderDropshadow(points), /*#__PURE__*/React.createElement("polyline", {
665
665
  fill: Colors[color],
666
666
  stroke: Colors[color],
667
667
  points: points.join(" ")
668
- }), /*#__PURE__*/createElement("polyline", {
668
+ }), /*#__PURE__*/React.createElement("polyline", {
669
669
  // Redraw the stroke on top of the background color,
670
670
  // so that the ends aren't extra dark where they meet
671
671
  // the border of the tooltip.
672
672
  fill: Colors[color],
673
673
  points: points.join(" "),
674
674
  stroke: Colors.offBlack16
675
- }), /*#__PURE__*/createElement("polyline", {
675
+ }), /*#__PURE__*/React.createElement("polyline", {
676
676
  stroke: Colors[color],
677
677
  points: trimlinePoints.join(" ")
678
678
  }));
@@ -684,8 +684,8 @@ class TooltipTail extends Component {
684
684
  placement,
685
685
  updateRef
686
686
  } = this.props;
687
- return /*#__PURE__*/createElement(View, {
688
- style: [styles.tailContainer, _extends({}, offset), this._getContainerStyle()],
687
+ return /*#__PURE__*/React.createElement(View, {
688
+ style: [styles$2.tailContainer, _extends({}, offset), this._getContainerStyle()],
689
689
  "data-placement": placement,
690
690
  ref: updateRef
691
691
  }, this._renderArrow());
@@ -706,7 +706,7 @@ const DISTANCE_FROM_ANCHOR = Spacing.xSmall_8;
706
706
  const MIN_DISTANCE_FROM_CORNERS = Spacing.xSmall_8;
707
707
  const ARROW_WIDTH = Spacing.large_24;
708
708
  const ARROW_HEIGHT = Spacing.small_12;
709
- const styles = StyleSheet.create({
709
+ const styles$2 = StyleSheet.create({
710
710
  /**
711
711
  * Container
712
712
  */
@@ -724,7 +724,7 @@ const styles = StyleSheet.create({
724
724
  }
725
725
  });
726
726
 
727
- class TooltipBubble extends Component {
727
+ class TooltipBubble extends React.Component {
728
728
  constructor(...args) {
729
729
  super(...args);
730
730
  this.state = {
@@ -758,7 +758,7 @@ class TooltipBubble extends Component {
758
758
  updateTailRef,
759
759
  tailOffset
760
760
  } = this.props;
761
- return /*#__PURE__*/createElement(View, {
761
+ return /*#__PURE__*/React.createElement(View, {
762
762
  id: id,
763
763
  role: "tooltip",
764
764
  "data-placement": placement,
@@ -766,9 +766,9 @@ class TooltipBubble extends Component {
766
766
  onMouseLeave: this.handleMouseLeave,
767
767
  ref: updateBubbleRef,
768
768
  style: [isReferenceHidden && styles$1.hide, styles$1.bubble, styles$1[`content-${placement}`], style]
769
- }, /*#__PURE__*/createElement(View, {
769
+ }, /*#__PURE__*/React.createElement(View, {
770
770
  style: styles$1.content
771
- }, children), /*#__PURE__*/createElement(TooltipTail, {
771
+ }, children), /*#__PURE__*/React.createElement(TooltipTail, {
772
772
  updateRef: updateTailRef,
773
773
  placement: placement,
774
774
  offset: tailOffset
@@ -823,7 +823,7 @@ const styles$1 = StyleSheet.create({
823
823
  * This component is used to provide the content that is to be rendered in the
824
824
  * tooltip bubble.
825
825
  */
826
- class TooltipContent extends Component {
826
+ class TooltipContent extends React.Component {
827
827
  _renderTitle() {
828
828
  const {
829
829
  title
@@ -831,7 +831,7 @@ class TooltipContent extends Component {
831
831
 
832
832
  if (title) {
833
833
  if (typeof title === "string") {
834
- return /*#__PURE__*/createElement(HeadingSmall, null, title);
834
+ return /*#__PURE__*/React.createElement(HeadingSmall, null, title);
835
835
  } else {
836
836
  return title;
837
837
  }
@@ -846,7 +846,7 @@ class TooltipContent extends Component {
846
846
  } = this.props;
847
847
 
848
848
  if (typeof children === "string") {
849
- return /*#__PURE__*/createElement(LabelMedium, null, children);
849
+ return /*#__PURE__*/React.createElement(LabelMedium, null, children);
850
850
  } else {
851
851
  return children;
852
852
  }
@@ -857,16 +857,16 @@ class TooltipContent extends Component {
857
857
 
858
858
  const children = this._renderChildren();
859
859
 
860
- const containerStyle = title ? styles$2.withTitle : styles$2.withoutTitle;
861
- return /*#__PURE__*/createElement(View, {
860
+ const containerStyle = title ? styles.withTitle : styles.withoutTitle;
861
+ return /*#__PURE__*/React.createElement(View, {
862
862
  style: containerStyle
863
- }, title, title && children && /*#__PURE__*/createElement(Strut, {
863
+ }, title, title && children && /*#__PURE__*/React.createElement(Strut, {
864
864
  size: Spacing.xxxSmall_4
865
865
  }), children);
866
866
  }
867
867
 
868
868
  }
869
- const styles$2 = StyleSheet.create({
869
+ const styles = StyleSheet.create({
870
870
  withoutTitle: {
871
871
  padding: `10px ${Spacing.medium_16}px`
872
872
  },
@@ -888,7 +888,7 @@ class RefTracker {
888
888
  // We only want to update the reference if it is
889
889
  // actually changed. Otherwise, we can trigger another render that
890
890
  // would then update the reference again and just keep looping.
891
- const domNode = findDOMNode(ref);
891
+ const domNode = ReactDOM.findDOMNode(ref);
892
892
 
893
893
  if (domNode instanceof HTMLElement && domNode !== this._lastRef) {
894
894
  this._lastRef = domNode;
@@ -918,7 +918,7 @@ class RefTracker {
918
918
  * This component is a light wrapper for react-popper, allowing us to position
919
919
  * and control the tooltip bubble location and visibility as we need.
920
920
  */
921
- class TooltipPopper extends Component {
921
+ class TooltipPopper extends React.Component {
922
922
  constructor(...args) {
923
923
  super(...args);
924
924
  this._bubbleRefTracker = new RefTracker();
@@ -975,7 +975,7 @@ class TooltipPopper extends Component {
975
975
  anchorElement,
976
976
  placement
977
977
  } = this.props;
978
- return /*#__PURE__*/createElement(Popper, {
978
+ return /*#__PURE__*/React.createElement(Popper, {
979
979
  referenceElement: anchorElement,
980
980
  strategy: "fixed",
981
981
  placement: placement,
@@ -1009,7 +1009,7 @@ class TooltipPopper extends Component {
1009
1009
  * - TooltipTail (renders the callout tail and shadow that points from the
1010
1010
  * callout to the anchor content)
1011
1011
  */
1012
- class Tooltip extends Component {
1012
+ class Tooltip extends React.Component {
1013
1013
  constructor(...args) {
1014
1014
  super(...args);
1015
1015
  this.state = {
@@ -1034,11 +1034,11 @@ class Tooltip extends Component {
1034
1034
  } = this.props;
1035
1035
 
1036
1036
  if (typeof content === "string") {
1037
- return /*#__PURE__*/createElement(TooltipContent, {
1037
+ return /*#__PURE__*/React.createElement(TooltipContent, {
1038
1038
  title: title
1039
1039
  }, content);
1040
1040
  } else if (title) {
1041
- return /*#__PURE__*/cloneElement(content, {
1041
+ return /*#__PURE__*/React.cloneElement(content, {
1042
1042
  title
1043
1043
  });
1044
1044
  } else {
@@ -1059,10 +1059,10 @@ class Tooltip extends Component {
1059
1059
  const {
1060
1060
  placement
1061
1061
  } = this.props;
1062
- return /*#__PURE__*/createElement(TooltipPopper, {
1062
+ return /*#__PURE__*/React.createElement(TooltipPopper, {
1063
1063
  anchorElement: this.state.anchorElement,
1064
1064
  placement: placement
1065
- }, props => /*#__PURE__*/createElement(TooltipBubble, {
1065
+ }, props => /*#__PURE__*/React.createElement(TooltipBubble, {
1066
1066
  id: bubbleId,
1067
1067
  style: props.style,
1068
1068
  tailOffset: props.tailOffset,
@@ -1096,14 +1096,14 @@ class Tooltip extends Component {
1096
1096
  const popperHost = this._getHost(); // TODO(kevinb): update to use ReactPopper's React 16-friendly syntax
1097
1097
 
1098
1098
 
1099
- return /*#__PURE__*/createElement(Fragment, null, /*#__PURE__*/createElement(TooltipAnchor, {
1099
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TooltipAnchor, {
1100
1100
  forceAnchorFocusivity: forceAnchorFocusivity,
1101
1101
  anchorRef: r => this._updateAnchorElement(r),
1102
1102
  onActiveChanged: active => this.setState({
1103
1103
  active
1104
1104
  }),
1105
1105
  ids: ids
1106
- }, children), popperHost && (active || activeBubble) && /*#__PURE__*/createPortal(this._renderPopper(ids), popperHost));
1106
+ }, children), popperHost && (active || activeBubble) && /*#__PURE__*/ReactDOM.createPortal(this._renderPopper(ids), popperHost));
1107
1107
  }
1108
1108
 
1109
1109
  render() {
@@ -1116,7 +1116,7 @@ class Tooltip extends Component {
1116
1116
  // need it.
1117
1117
  return this._renderTooltipAnchor();
1118
1118
  } else {
1119
- return /*#__PURE__*/createElement(UniqueIDProvider, {
1119
+ return /*#__PURE__*/React.createElement(UniqueIDProvider, {
1120
1120
  scope: "tooltip",
1121
1121
  mockOnFirstRender: true
1122
1122
  }, ids => this._renderTooltipAnchor(ids));
@@ -1130,5 +1130,4 @@ Tooltip.defaultProps = {
1130
1130
  };
1131
1131
  Tooltip.ariaContentId = "aria-content";
1132
1132
 
1133
- export default Tooltip;
1134
- export { TooltipContent, TooltipPopper, TooltipTail };
1133
+ export { TooltipContent, TooltipPopper, TooltipTail, Tooltip as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-tooltip",
3
- "version": "1.3.3",
3
+ "version": "1.3.7",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -15,23 +15,22 @@
15
15
  "author": "",
16
16
  "license": "MIT",
17
17
  "dependencies": {
18
- "@babel/runtime": "^7.13.10",
19
- "@khanacademy/wonder-blocks-color": "^1.1.19",
20
- "@khanacademy/wonder-blocks-core": "^3.1.5",
21
- "@khanacademy/wonder-blocks-layout": "^1.4.4",
22
- "@khanacademy/wonder-blocks-modal": "^2.1.43",
23
- "@khanacademy/wonder-blocks-spacing": "^3.0.4",
24
- "@khanacademy/wonder-blocks-typography": "^1.1.26"
18
+ "@babel/runtime": "^7.16.3",
19
+ "@khanacademy/wonder-blocks-color": "^1.1.20",
20
+ "@khanacademy/wonder-blocks-core": "^4.2.1",
21
+ "@khanacademy/wonder-blocks-layout": "^1.4.7",
22
+ "@khanacademy/wonder-blocks-modal": "^2.2.1",
23
+ "@khanacademy/wonder-blocks-spacing": "^3.0.5",
24
+ "@khanacademy/wonder-blocks-typography": "^1.1.29"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "@popperjs/core": "^2.10.1",
28
28
  "aphrodite": "^1.2.5",
29
- "react": "^16.4.1",
30
- "react-dom": "^16.4.1",
29
+ "react": "16.14.0",
30
+ "react-dom": "16.14.0",
31
31
  "react-popper": "^2.0.0"
32
32
  },
33
33
  "devDependencies": {
34
- "wb-dev-build-settings": "^0.1.2"
35
- },
36
- "gitHead": "7e879c62ab49bf48f1debb96bcbc9d612e4689a6"
34
+ "wb-dev-build-settings": "^0.3.0"
35
+ }
37
36
  }
@@ -142,8 +142,8 @@ exports[`wonder-blocks-tooltip example 3 1`] = `
142
142
 
143
143
  exports[`wonder-blocks-tooltip example 4 1`] = `
144
144
  <button
145
+ aria-disabled={false}
145
146
  className=""
146
- disabled={false}
147
147
  onBlur={[Function]}
148
148
  onClick={[Function]}
149
149
  onDragStart={[Function]}
@@ -400,8 +400,8 @@ exports[`wonder-blocks-tooltip example 6 1`] = `
400
400
  >
401
401
  <button
402
402
  aria-describedby="uid-tooltip-6-aria-content"
403
+ aria-disabled={false}
403
404
  className=""
404
- disabled={false}
405
405
  onBlur={[Function]}
406
406
  onClick={[Function]}
407
407
  onDragStart={[Function]}
@@ -4,6 +4,7 @@
4
4
  import * as React from "react";
5
5
  import {View} from "@khanacademy/wonder-blocks-core";
6
6
  import {mount} from "enzyme";
7
+ import "jest-enzyme";
7
8
 
8
9
  import TooltipAnchor from "../tooltip-anchor.js";
9
10
  import {
@@ -128,7 +129,7 @@ describe("TooltipAnchor", () => {
128
129
  });
129
130
 
130
131
  // Act
131
- const result = ref && ref.getAttribute("tabindex");
132
+ const result = ref?.getAttribute("tabindex");
132
133
 
133
134
  // Assert
134
135
  expect(result).toBe("0");
@@ -150,7 +151,7 @@ describe("TooltipAnchor", () => {
150
151
  });
151
152
 
152
153
  // Act
153
- const result = ref && ref.getAttribute("tabindex");
154
+ const result = ref?.getAttribute("tabindex");
154
155
 
155
156
  // Assert
156
157
  expect(result).toBe("-1");
@@ -174,7 +175,7 @@ describe("TooltipAnchor", () => {
174
175
  });
175
176
 
176
177
  // Act
177
- const result = ref && ref.getAttribute("tabindex");
178
+ const result = ref?.getAttribute("tabindex");
178
179
 
179
180
  // Assert
180
181
  expect(result).toBeNull();
@@ -197,11 +198,11 @@ describe("TooltipAnchor", () => {
197
198
  });
198
199
 
199
200
  // Act
200
- const tabindex = ref && ref.getAttribute("tabindex");
201
+ const tabindex = ref?.getAttribute("tabindex");
201
202
  expect(tabindex).toBe("0");
202
203
 
203
- wrapper && wrapper.setProps({force: false});
204
- const result = ref && ref.getAttribute("tabindex");
204
+ wrapper?.setProps({force: false});
205
+ const result = ref?.getAttribute("tabindex");
205
206
 
206
207
  // Assert
207
208
  expect(result).toBeNull();
@@ -224,7 +225,7 @@ describe("TooltipAnchor", () => {
224
225
  });
225
226
 
226
227
  // Act
227
- const result = ref && ref.getAttribute("tabindex");
228
+ const result = ref?.getAttribute("tabindex");
228
229
 
229
230
  // Assert
230
231
  expect(result).not.toBeNull();
@@ -237,6 +238,7 @@ describe("TooltipAnchor", () => {
237
238
  const {default: ActiveTracker} = await import(
238
239
  "../../util/active-tracker.js"
239
240
  );
241
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
240
242
  // Let's tell the tooltip it isn't stealing and therefore it should
241
243
  // be using a delay to show the tooltip.
242
244
  // Flow doesn't know this is a mock
@@ -265,10 +267,10 @@ describe("TooltipAnchor", () => {
265
267
  // whether focused directly or a child is focused). We have to
266
268
  // fake directly because there's no real browser here handling
267
269
  // focus and real events.
268
- ref && ref.dispatchEvent(new FocusEvent("focusin"));
270
+ ref?.dispatchEvent(new FocusEvent("focusin"));
269
271
  // Check that we didn't go active before the delay
270
272
  expect(activeState).toBe(false);
271
- expect(setTimeout).toHaveBeenLastCalledWith(
273
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
272
274
  expect.any(Function),
273
275
  TooltipAppearanceDelay,
274
276
  );
@@ -310,7 +312,7 @@ describe("TooltipAnchor", () => {
310
312
  // whether focused directly or a child is focused). We have to
311
313
  // fake directly because there's no real browser here handling
312
314
  // focus and real events.
313
- ref && ref.dispatchEvent(new FocusEvent("focusin"));
315
+ ref?.dispatchEvent(new FocusEvent("focusin"));
314
316
 
315
317
  // Assert
316
318
  expect(activeState).toBe(true);
@@ -320,6 +322,7 @@ describe("TooltipAnchor", () => {
320
322
  describe("loses keyboard focus", () => {
321
323
  test("active state was not stolen, active is set to false with delay", async () => {
322
324
  // Arrange
325
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
323
326
  let activeState = false;
324
327
  const ref = await new Promise((resolve) => {
325
328
  const nodes = (
@@ -335,8 +338,8 @@ describe("TooltipAnchor", () => {
335
338
  mount(nodes);
336
339
  });
337
340
 
338
- ref && ref.dispatchEvent(new FocusEvent("focusin"));
339
- expect(setTimeout).toHaveBeenLastCalledWith(
341
+ ref?.dispatchEvent(new FocusEvent("focusin"));
342
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
340
343
  expect.any(Function),
341
344
  TooltipAppearanceDelay,
342
345
  );
@@ -344,9 +347,9 @@ describe("TooltipAnchor", () => {
344
347
  expect(activeState).toBe(true);
345
348
 
346
349
  // Act
347
- ref && ref.dispatchEvent(new FocusEvent("focusout"));
350
+ ref?.dispatchEvent(new FocusEvent("focusout"));
348
351
  expect(activeState).toBe(true);
349
- expect(setTimeout).toHaveBeenLastCalledWith(
352
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
350
353
  expect.any(Function),
351
354
  TooltipDisappearanceDelay,
352
355
  );
@@ -358,6 +361,7 @@ describe("TooltipAnchor", () => {
358
361
 
359
362
  test("active state was not stolen, gives up active state", async () => {
360
363
  // Arrange
364
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
361
365
  const {default: ActiveTracker} = await import(
362
366
  "../../util/active-tracker.js"
363
367
  );
@@ -380,8 +384,8 @@ describe("TooltipAnchor", () => {
380
384
  mount(nodes);
381
385
  });
382
386
 
383
- ref && ref.dispatchEvent(new FocusEvent("focusin"));
384
- expect(setTimeout).toHaveBeenLastCalledWith(
387
+ ref?.dispatchEvent(new FocusEvent("focusin"));
388
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
385
389
  expect.any(Function),
386
390
  TooltipAppearanceDelay,
387
391
  );
@@ -389,9 +393,9 @@ describe("TooltipAnchor", () => {
389
393
  expect(activeState).toBe(true);
390
394
 
391
395
  // Act
392
- ref && ref.dispatchEvent(new FocusEvent("focusout"));
396
+ ref?.dispatchEvent(new FocusEvent("focusout"));
393
397
  expect(activeState).toBe(true);
394
- expect(setTimeout).toHaveBeenLastCalledWith(
398
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
395
399
  expect.any(Function),
396
400
  TooltipDisappearanceDelay,
397
401
  );
@@ -403,6 +407,7 @@ describe("TooltipAnchor", () => {
403
407
 
404
408
  test("active state was stolen, active is set to false immediately", async () => {
405
409
  // Arrange
410
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
406
411
  let wrapper;
407
412
  let activeState = false;
408
413
  const ref = await new Promise((resolve) => {
@@ -419,8 +424,8 @@ describe("TooltipAnchor", () => {
419
424
  wrapper = mount(nodes);
420
425
  });
421
426
 
422
- ref && ref.dispatchEvent(new FocusEvent("focusin"));
423
- expect(setTimeout).toHaveBeenLastCalledWith(
427
+ ref?.dispatchEvent(new FocusEvent("focusin"));
428
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
424
429
  expect.any(Function),
425
430
  TooltipAppearanceDelay,
426
431
  );
@@ -428,8 +433,8 @@ describe("TooltipAnchor", () => {
428
433
  expect(activeState).toBe(true);
429
434
 
430
435
  // Act
431
- ref && ref.dispatchEvent(new FocusEvent("focusout"));
432
- wrapper && wrapper.instance().activeStateStolen();
436
+ ref?.dispatchEvent(new FocusEvent("focusout"));
437
+ wrapper?.instance().activeStateStolen();
433
438
 
434
439
  // Assert
435
440
  expect(activeState).toBe(false);
@@ -437,6 +442,7 @@ describe("TooltipAnchor", () => {
437
442
 
438
443
  test("active state was stolen, so it does not have it to give up", async () => {
439
444
  // Arrange
445
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
440
446
  const {default: ActiveTracker} = await import(
441
447
  "../../util/active-tracker.js"
442
448
  );
@@ -459,8 +465,8 @@ describe("TooltipAnchor", () => {
459
465
  );
460
466
  wrapper = mount(nodes);
461
467
  });
462
- ref && ref.dispatchEvent(new FocusEvent("focusin"));
463
- expect(setTimeout).toHaveBeenLastCalledWith(
468
+ ref?.dispatchEvent(new FocusEvent("focusin"));
469
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
464
470
  expect.any(Function),
465
471
  TooltipAppearanceDelay,
466
472
  );
@@ -468,8 +474,8 @@ describe("TooltipAnchor", () => {
468
474
  expect(activeState).toBe(true);
469
475
 
470
476
  // Act
471
- ref && ref.dispatchEvent(new FocusEvent("focusout"));
472
- wrapper && wrapper.instance().activeStateStolen();
477
+ ref?.dispatchEvent(new FocusEvent("focusout"));
478
+ wrapper?.instance().activeStateStolen();
473
479
 
474
480
  // Assert
475
481
  expect(mockTracker.giveup).not.toHaveBeenCalled();
@@ -477,6 +483,7 @@ describe("TooltipAnchor", () => {
477
483
 
478
484
  test("if hovered, remains active", async () => {
479
485
  // Arrange
486
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
480
487
  let activeState = false;
481
488
  const ref = await new Promise((resolve) => {
482
489
  const nodes = (
@@ -491,30 +498,29 @@ describe("TooltipAnchor", () => {
491
498
  );
492
499
  mount(nodes);
493
500
  });
494
- ref && ref.dispatchEvent(new FocusEvent("focusin"));
495
- expect(setTimeout).toHaveBeenLastCalledWith(
501
+ ref?.dispatchEvent(new FocusEvent("focusin"));
502
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
496
503
  expect.any(Function),
497
504
  TooltipAppearanceDelay,
498
505
  );
499
506
  jest.runOnlyPendingTimers();
500
- // Flow doesn't know we added jest mocks to this
501
- // $FlowFixMe[prop-missing]
502
- setTimeout.mockClear();
503
- ref && ref.dispatchEvent(new MouseEvent("mouseenter"));
507
+ timeoutSpy.mockClear();
508
+ ref?.dispatchEvent(new MouseEvent("mouseenter"));
504
509
 
505
510
  // Act
506
- ref && ref.dispatchEvent(new FocusEvent("focusout"));
511
+ ref?.dispatchEvent(new FocusEvent("focusout"));
507
512
 
508
513
  // Assert
509
514
  // Make sure that we're not delay hiding as well.
510
515
  expect(activeState).toBe(true);
511
- expect(setTimeout).not.toHaveBeenCalled();
516
+ expect(timeoutSpy).not.toHaveBeenCalled();
512
517
  });
513
518
  });
514
519
 
515
520
  describe("is hovered", () => {
516
521
  test("active state was not stolen, delays set active", async () => {
517
522
  // Arrange
523
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
518
524
  const {default: ActiveTracker} = await import(
519
525
  "../../util/active-tracker.js"
520
526
  );
@@ -541,10 +547,10 @@ describe("TooltipAnchor", () => {
541
547
  });
542
548
 
543
549
  // Act
544
- ref && ref.dispatchEvent(new MouseEvent("mouseenter"));
550
+ ref?.dispatchEvent(new MouseEvent("mouseenter"));
545
551
  // Check that we didn't go active before the delay
546
552
  expect(activeState).toBe(false);
547
- expect(setTimeout).toHaveBeenLastCalledWith(
553
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
548
554
  expect.any(Function),
549
555
  TooltipAppearanceDelay,
550
556
  );
@@ -582,7 +588,7 @@ describe("TooltipAnchor", () => {
582
588
  });
583
589
 
584
590
  // Act
585
- ref && ref.dispatchEvent(new MouseEvent("mouseenter"));
591
+ ref?.dispatchEvent(new MouseEvent("mouseenter"));
586
592
 
587
593
  // Assert
588
594
  expect(activeState).toBe(true);
@@ -592,6 +598,7 @@ describe("TooltipAnchor", () => {
592
598
  describe("is unhovered", () => {
593
599
  test("active state was not stolen, active is set to false with delay", async () => {
594
600
  // Arrange
601
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
595
602
  let activeState = false;
596
603
  const ref = await new Promise((resolve) => {
597
604
  const nodes = (
@@ -606,8 +613,8 @@ describe("TooltipAnchor", () => {
606
613
  );
607
614
  mount(nodes);
608
615
  });
609
- ref && ref.dispatchEvent(new MouseEvent("mouseenter"));
610
- expect(setTimeout).toHaveBeenLastCalledWith(
616
+ ref?.dispatchEvent(new MouseEvent("mouseenter"));
617
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
611
618
  expect.any(Function),
612
619
  TooltipAppearanceDelay,
613
620
  );
@@ -615,9 +622,9 @@ describe("TooltipAnchor", () => {
615
622
  expect(activeState).toBe(true);
616
623
 
617
624
  // Act
618
- ref && ref.dispatchEvent(new MouseEvent("mouseleave"));
625
+ ref?.dispatchEvent(new MouseEvent("mouseleave"));
619
626
  expect(activeState).toBe(true);
620
- expect(setTimeout).toHaveBeenLastCalledWith(
627
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
621
628
  expect.any(Function),
622
629
  TooltipDisappearanceDelay,
623
630
  );
@@ -629,6 +636,7 @@ describe("TooltipAnchor", () => {
629
636
 
630
637
  test("active state was not stolen, gives up active state", async () => {
631
638
  // Arrange
639
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
632
640
  const {default: ActiveTracker} = await import(
633
641
  "../../util/active-tracker.js"
634
642
  );
@@ -649,8 +657,8 @@ describe("TooltipAnchor", () => {
649
657
  );
650
658
  mount(nodes);
651
659
  });
652
- ref && ref.dispatchEvent(new MouseEvent("mouseenter"));
653
- expect(setTimeout).toHaveBeenLastCalledWith(
660
+ ref?.dispatchEvent(new MouseEvent("mouseenter"));
661
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
654
662
  expect.any(Function),
655
663
  TooltipAppearanceDelay,
656
664
  );
@@ -658,9 +666,9 @@ describe("TooltipAnchor", () => {
658
666
  expect(activeState).toBe(true);
659
667
 
660
668
  // Act
661
- ref && ref.dispatchEvent(new MouseEvent("mouseleave"));
669
+ ref?.dispatchEvent(new MouseEvent("mouseleave"));
662
670
  expect(activeState).toBe(true);
663
- expect(setTimeout).toHaveBeenLastCalledWith(
671
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
664
672
  expect.any(Function),
665
673
  TooltipDisappearanceDelay,
666
674
  );
@@ -672,6 +680,7 @@ describe("TooltipAnchor", () => {
672
680
 
673
681
  test("active state was stolen, active is set to false immediately", async () => {
674
682
  // Arrange
683
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
675
684
  let wrapper;
676
685
  let activeState = false;
677
686
  const ref = await new Promise((resolve) => {
@@ -687,8 +696,8 @@ describe("TooltipAnchor", () => {
687
696
  );
688
697
  wrapper = mount(nodes);
689
698
  });
690
- ref && ref.dispatchEvent(new MouseEvent("mouseenter"));
691
- expect(setTimeout).toHaveBeenLastCalledWith(
699
+ ref?.dispatchEvent(new MouseEvent("mouseenter"));
700
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
692
701
  expect.any(Function),
693
702
  TooltipAppearanceDelay,
694
703
  );
@@ -696,8 +705,8 @@ describe("TooltipAnchor", () => {
696
705
  expect(activeState).toBe(true);
697
706
 
698
707
  // Act
699
- ref && ref.dispatchEvent(new MouseEvent("mouseleave"));
700
- wrapper && wrapper.instance().activeStateStolen();
708
+ ref?.dispatchEvent(new MouseEvent("mouseleave"));
709
+ wrapper?.instance().activeStateStolen();
701
710
 
702
711
  // Assert
703
712
  expect(activeState).toBe(false);
@@ -705,6 +714,7 @@ describe("TooltipAnchor", () => {
705
714
 
706
715
  test("active state was stolen, so it does not have it to give up", async () => {
707
716
  // Arrange
717
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
708
718
  const {default: ActiveTracker} = await import(
709
719
  "../../util/active-tracker.js"
710
720
  );
@@ -727,8 +737,8 @@ describe("TooltipAnchor", () => {
727
737
  );
728
738
  wrapper = mount(nodes);
729
739
  });
730
- ref && ref.dispatchEvent(new MouseEvent("mouseenter"));
731
- expect(setTimeout).toHaveBeenLastCalledWith(
740
+ ref?.dispatchEvent(new MouseEvent("mouseenter"));
741
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
732
742
  expect.any(Function),
733
743
  TooltipAppearanceDelay,
734
744
  );
@@ -736,8 +746,8 @@ describe("TooltipAnchor", () => {
736
746
  expect(activeState).toBe(true);
737
747
 
738
748
  // Act
739
- ref && ref.dispatchEvent(new MouseEvent("mouseleave"));
740
- wrapper && wrapper.instance().activeStateStolen();
749
+ ref?.dispatchEvent(new MouseEvent("mouseleave"));
750
+ wrapper?.instance().activeStateStolen();
741
751
 
742
752
  // Assert
743
753
  expect(mockTracker.giveup).not.toHaveBeenCalled();
@@ -745,6 +755,7 @@ describe("TooltipAnchor", () => {
745
755
 
746
756
  test("if focused, remains active", async () => {
747
757
  // Arrange
758
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
748
759
  let activeState = false;
749
760
  const ref = await new Promise((resolve) => {
750
761
  const nodes = (
@@ -759,30 +770,29 @@ describe("TooltipAnchor", () => {
759
770
  );
760
771
  mount(nodes);
761
772
  });
762
- ref && ref.dispatchEvent(new MouseEvent("mouseenter"));
763
- expect(setTimeout).toHaveBeenLastCalledWith(
773
+ ref?.dispatchEvent(new MouseEvent("mouseenter"));
774
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
764
775
  expect.any(Function),
765
776
  TooltipAppearanceDelay,
766
777
  );
767
778
  jest.runOnlyPendingTimers();
768
- // Flow doesn't know we added jest mocks to this
769
- // $FlowFixMe[prop-missing]
770
- setTimeout.mockClear();
771
- ref && ref.dispatchEvent(new FocusEvent("focusin"));
779
+ timeoutSpy.mockClear();
780
+ ref?.dispatchEvent(new FocusEvent("focusin"));
772
781
 
773
782
  // Act
774
- ref && ref.dispatchEvent(new MouseEvent("mouseleave"));
783
+ ref?.dispatchEvent(new MouseEvent("mouseleave"));
775
784
 
776
785
  // Assert
777
786
  // Make sure that we're not delay hiding as well.
778
787
  expect(activeState).toBe(true);
779
- expect(setTimeout).not.toHaveBeenCalled();
788
+ expect(timeoutSpy).not.toHaveBeenCalled();
780
789
  });
781
790
  });
782
791
 
783
792
  describe("dismiss behavior", () => {
784
793
  test("subscribes to keydown event on active", async () => {
785
794
  // Arrange
795
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
786
796
  const spy = jest.spyOn(document, "addEventListener");
787
797
  const ref = await new Promise((resolve) => {
788
798
  const nodes = (
@@ -797,8 +807,8 @@ describe("TooltipAnchor", () => {
797
807
  });
798
808
 
799
809
  // Act
800
- ref && ref.dispatchEvent(new MouseEvent("mouseenter"));
801
- expect(setTimeout).toHaveBeenLastCalledWith(
810
+ ref?.dispatchEvent(new MouseEvent("mouseenter"));
811
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
802
812
  expect.any(Function),
803
813
  TooltipAppearanceDelay,
804
814
  );
@@ -811,6 +821,7 @@ describe("TooltipAnchor", () => {
811
821
 
812
822
  test("does not subscribe to keydown event if already active", async () => {
813
823
  // Arrange
824
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
814
825
  const spy = jest.spyOn(document, "addEventListener");
815
826
  const ref = await new Promise((resolve) => {
816
827
  const nodes = (
@@ -824,8 +835,8 @@ describe("TooltipAnchor", () => {
824
835
  mount(nodes);
825
836
  });
826
837
 
827
- ref && ref.dispatchEvent(new KeyboardEvent("focusin"));
828
- expect(setTimeout).toHaveBeenLastCalledWith(
838
+ ref?.dispatchEvent(new KeyboardEvent("focusin"));
839
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
829
840
  expect.any(Function),
830
841
  TooltipAppearanceDelay,
831
842
  );
@@ -835,7 +846,7 @@ describe("TooltipAnchor", () => {
835
846
  spy.mockClear();
836
847
 
837
848
  // Act
838
- ref && ref.dispatchEvent(new MouseEvent("mouseenter"));
849
+ ref?.dispatchEvent(new MouseEvent("mouseenter"));
839
850
 
840
851
  // Assert
841
852
  expect(spy).not.toHaveBeenCalled();
@@ -843,6 +854,7 @@ describe("TooltipAnchor", () => {
843
854
 
844
855
  test("unsubscribes from keydown event on inactive", async () => {
845
856
  // Arrange
857
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
846
858
  const spy = jest.spyOn(document, "removeEventListener");
847
859
  const ref = await new Promise((resolve) => {
848
860
  const nodes = (
@@ -856,16 +868,16 @@ describe("TooltipAnchor", () => {
856
868
  mount(nodes);
857
869
  });
858
870
 
859
- ref && ref.dispatchEvent(new KeyboardEvent("focusin"));
860
- expect(setTimeout).toHaveBeenLastCalledWith(
871
+ ref?.dispatchEvent(new KeyboardEvent("focusin"));
872
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
861
873
  expect.any(Function),
862
874
  TooltipAppearanceDelay,
863
875
  );
864
876
  jest.runOnlyPendingTimers();
865
877
 
866
878
  // Act
867
- ref && ref.dispatchEvent(new KeyboardEvent("focusout"));
868
- expect(setTimeout).toHaveBeenLastCalledWith(
879
+ ref?.dispatchEvent(new KeyboardEvent("focusout"));
880
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
869
881
  expect.any(Function),
870
882
  TooltipDisappearanceDelay,
871
883
  );
@@ -878,6 +890,7 @@ describe("TooltipAnchor", () => {
878
890
 
879
891
  test("unsubscribes from keydown event on unmount", async () => {
880
892
  // Arrange
893
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
881
894
  let wrapper;
882
895
  const spy = jest.spyOn(document, "removeEventListener");
883
896
  const ref = await new Promise((resolve) => {
@@ -892,15 +905,15 @@ describe("TooltipAnchor", () => {
892
905
  wrapper = mount(nodes);
893
906
  });
894
907
 
895
- ref && ref.dispatchEvent(new KeyboardEvent("focusin"));
896
- expect(setTimeout).toHaveBeenLastCalledWith(
908
+ ref?.dispatchEvent(new KeyboardEvent("focusin"));
909
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
897
910
  expect.any(Function),
898
911
  TooltipAppearanceDelay,
899
912
  );
900
913
  jest.runOnlyPendingTimers();
901
914
 
902
915
  // Act
903
- wrapper && wrapper.unmount();
916
+ wrapper?.unmount();
904
917
 
905
918
  // Assert
906
919
  expect(spy).toHaveBeenCalledTimes(1);
@@ -909,6 +922,7 @@ describe("TooltipAnchor", () => {
909
922
 
910
923
  test("when active, escape dismisses tooltip", async () => {
911
924
  // Arrange
925
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
912
926
  let activeState = false;
913
927
  const ref = await new Promise((resolve) => {
914
928
  const nodes = (
@@ -924,20 +938,22 @@ describe("TooltipAnchor", () => {
924
938
  mount(nodes);
925
939
  });
926
940
 
927
- ref && ref.dispatchEvent(new KeyboardEvent("focusin"));
928
- expect(setTimeout).toHaveBeenLastCalledWith(
941
+ ref?.dispatchEvent(new KeyboardEvent("focusin"));
942
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
929
943
  expect.any(Function),
930
944
  TooltipAppearanceDelay,
931
945
  );
932
946
  jest.runOnlyPendingTimers();
933
947
  const event: KeyboardEvent = (document.createEvent("Event"): any);
948
+ // $FlowIgnore[cannot-write]
934
949
  event.key = "Escape";
950
+ // $FlowIgnore[cannot-write]
935
951
  event.which = 27;
936
952
  event.initEvent("keyup", true, true);
937
953
 
938
954
  // Act
939
955
  document.dispatchEvent(event);
940
- expect(setTimeout).toHaveBeenLastCalledWith(
956
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
941
957
  expect.any(Function),
942
958
  TooltipDisappearanceDelay,
943
959
  );
@@ -949,6 +965,7 @@ describe("TooltipAnchor", () => {
949
965
 
950
966
  test("when active, escape stops event propagation", async () => {
951
967
  // Arrange
968
+ const timeoutSpy = jest.spyOn(global, "setTimeout");
952
969
  const ref = await new Promise((resolve) => {
953
970
  const nodes = (
954
971
  <TooltipAnchor
@@ -961,20 +978,21 @@ describe("TooltipAnchor", () => {
961
978
  mount(nodes);
962
979
  });
963
980
 
964
- ref && ref.dispatchEvent(new KeyboardEvent("focusin"));
965
- expect(setTimeout).toHaveBeenLastCalledWith(
981
+ ref?.dispatchEvent(new KeyboardEvent("focusin"));
982
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
966
983
  expect.any(Function),
967
984
  TooltipAppearanceDelay,
968
985
  );
969
986
  jest.runOnlyPendingTimers();
970
987
  const event: KeyboardEvent = (document.createEvent("Event"): any);
971
988
  const spyOnStopPropagation = jest.spyOn(event, "stopPropagation");
989
+ // $FlowIgnore[cannot-write]
972
990
  event.key = "Escape";
973
991
  event.initEvent("keyup", true, true);
974
992
 
975
993
  // Act
976
994
  document.dispatchEvent(event);
977
- expect(setTimeout).toHaveBeenLastCalledWith(
995
+ expect(timeoutSpy).toHaveBeenLastCalledWith(
978
996
  expect.any(Function),
979
997
  TooltipDisappearanceDelay,
980
998
  );
@@ -2,6 +2,7 @@
2
2
  import * as React from "react";
3
3
  import * as ReactDOM from "react-dom";
4
4
  import {mount} from "enzyme";
5
+ import "jest-enzyme";
5
6
 
6
7
  import {View} from "@khanacademy/wonder-blocks-core";
7
8
 
@@ -2,6 +2,7 @@
2
2
  import * as React from "react";
3
3
  import * as ReactDOM from "react-dom";
4
4
  import {mount} from "enzyme";
5
+ import "jest-enzyme";
5
6
 
6
7
  import {View} from "@khanacademy/wonder-blocks-core";
7
8
 
@@ -2,8 +2,6 @@
2
2
  import * as React from "react";
3
3
 
4
4
  import {render, screen, fireEvent} from "@testing-library/react";
5
- // eslint-disable-next-line import/no-unassigned-import
6
- import "@testing-library/jest-dom/extend-expect";
7
5
  import userEvent from "@testing-library/user-event";
8
6
 
9
7
  import Tooltip from "../tooltip.js";
@@ -56,6 +54,8 @@ describe("tooltip integration tests", () => {
56
54
  const anchor = screen.getByText("an anchor");
57
55
  userEvent.hover(anchor);
58
56
  // hover on bubble to keep it active
57
+ // Need to run the timers or we won't get the bubble wrapper to show.
58
+ jest.runAllTimers();
59
59
  const bubbleWrapper = await screen.findByRole("tooltip");
60
60
  userEvent.unhover(anchor);
61
61
 
@@ -2,6 +2,7 @@
2
2
  import * as React from "react";
3
3
  import * as ReactDOM from "react-dom";
4
4
  import {mount} from "enzyme";
5
+ import "jest-enzyme";
5
6
 
6
7
  import {View} from "@khanacademy/wonder-blocks-core";
7
8
  import {Body, HeadingSmall} from "@khanacademy/wonder-blocks-typography";
@@ -77,7 +77,8 @@ const TRACKER = new ActiveTracker();
77
77
 
78
78
  export default class TooltipAnchor
79
79
  extends React.Component<Props, State>
80
- implements IActiveTrackerSubscriber {
80
+ implements IActiveTrackerSubscriber
81
+ {
81
82
  _weSetFocusivity: ?boolean;
82
83
  _anchorNode: ?Element;
83
84
  _focused: boolean;
@@ -363,12 +363,8 @@ export default class TooltipTail extends React.Component<Props> {
363
363
  }
364
364
 
365
365
  _renderArrow(): React.Node {
366
- const {
367
- trimlinePoints,
368
- points,
369
- height,
370
- width,
371
- } = this._calculateDimensionsFromPlacement();
366
+ const {trimlinePoints, points, height, width} =
367
+ this._calculateDimensionsFromPlacement();
372
368
 
373
369
  const {color} = this.props;
374
370
 
@@ -2,18 +2,28 @@
2
2
  import * as React from "react";
3
3
  import {StyleSheet} from "aphrodite";
4
4
  import {View} from "@khanacademy/wonder-blocks-core";
5
+ import Button from "@khanacademy/wonder-blocks-button";
5
6
  import {TextField} from "@khanacademy/wonder-blocks-form";
7
+ import {Strut} from "@khanacademy/wonder-blocks-layout";
8
+ import Spacing from "@khanacademy/wonder-blocks-spacing";
6
9
  import Tooltip from "@khanacademy/wonder-blocks-tooltip";
7
10
 
8
11
  import type {Placement} from "@khanacademy/wonder-blocks-tooltip";
9
12
  import type {StoryComponentType} from "@storybook/react";
10
13
 
11
14
  export default {
12
- title: "Tooltip",
15
+ title: "Floating/Tooltip",
16
+ parameters: {
17
+ // TODO(WB-1170): Reassess this after investigating more about Chromatic
18
+ // flakyness.
19
+ chromatic: {
20
+ delay: 400,
21
+ },
22
+ },
13
23
  };
14
24
 
15
25
  const BaseTooltipExample = ({placement}: {|placement: Placement|}) => {
16
- const inputRef = React.useRef<null | HTMLElement>(null);
26
+ const inputRef = React.useRef(null);
17
27
  React.useEffect(() => {
18
28
  if (inputRef.current) {
19
29
  inputRef.current.focus();
@@ -41,19 +51,44 @@ const BaseTooltipExample = ({placement}: {|placement: Placement|}) => {
41
51
  );
42
52
  };
43
53
 
44
- export const tooltipRight: StoryComponentType = () => (
54
+ export const TooltipOnButtons: StoryComponentType = () => {
55
+ return (
56
+ <View style={styles.centered}>
57
+ <View>
58
+ <Tooltip content={"This is a tooltip on a button."}>
59
+ <Button disabled={false}>Example 1</Button>
60
+ </Tooltip>
61
+ <Strut size={Spacing.medium_16} />
62
+ <Tooltip
63
+ content="This is a tooltip on a disabled button."
64
+ placement="bottom"
65
+ >
66
+ <Button disabled={true}>Example 2</Button>
67
+ </Tooltip>
68
+ </View>
69
+ </View>
70
+ );
71
+ };
72
+
73
+ TooltipOnButtons.parameters = {
74
+ chromatic: {
75
+ disableSnapshot: true,
76
+ },
77
+ };
78
+
79
+ export const TooltipRight: StoryComponentType = () => (
45
80
  <BaseTooltipExample placement="right" />
46
81
  );
47
82
 
48
- export const tooltipLeft: StoryComponentType = () => (
83
+ export const TooltipLeft: StoryComponentType = () => (
49
84
  <BaseTooltipExample placement="left" />
50
85
  );
51
86
 
52
- export const tooltipTop: StoryComponentType = () => (
87
+ export const TooltipTop: StoryComponentType = () => (
53
88
  <BaseTooltipExample placement="top" />
54
89
  );
55
90
 
56
- export const tooltipBottom: StoryComponentType = () => (
91
+ export const TooltipBottom: StoryComponentType = () => (
57
92
  <BaseTooltipExample placement="bottom" />
58
93
  );
59
94
 
@@ -2,6 +2,7 @@
2
2
  import * as React from "react";
3
3
  import * as ReactDOM from "react-dom";
4
4
  import {mount} from "enzyme";
5
+ import "jest-enzyme";
5
6
 
6
7
  import {View} from "@khanacademy/wonder-blocks-core";
7
8
 
@@ -9,12 +9,10 @@ import * as React from "react";
9
9
  import * as ReactDOM from "react-dom";
10
10
 
11
11
  import type {PopperChildrenProps} from "react-popper";
12
- import type {getRefFn} from "./types.js";
13
12
 
14
13
  type PopperRef = $PropertyType<PopperChildrenProps, "ref">;
15
14
 
16
15
  export default class RefTracker {
17
- updateRef: getRefFn;
18
16
  _lastRef: ?HTMLElement;
19
17
  _targetFn: ?(?HTMLElement) => void;
20
18
 
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2018 Khan Academy
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.