react-tooltip 5.22.0-beta.1091.1 → 5.22.0-beta.1108.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -58,17 +58,26 @@ yarn add react-tooltip
58
58
 
59
59
  ## Sponsors
60
60
 
61
+ ### Gold Sponsors 🌟
62
+
61
63
  <a href="https://frigade.com/?source=react-tooltip">
62
- <img alt="Frigade" style="height: 250px" src="docs/static/img/sponsors/frigade.png" />
64
+ <img alt="Frigade" style="height: 250px;" src="docs/static/img/sponsors/frigade.png" />
63
65
  </a>
64
66
 
65
67
  React Tooltip is proud to be sponsored by [Frigade](https://frigade.com/?source=react-tooltip), a developer tool for building better product onboarding: guided tours, getting started checklists, announcements, etc.
66
68
 
69
+ #### Silver Sponsors ✪
70
+
71
+ <a href="https://dopt.com/?source=react-tooltip">
72
+ <img alt="Dopt" style="height: 200px; width: 200px;" src="docs/static/img/sponsors/dopt.png" />
73
+ </a>
74
+
67
75
  ## Usage
68
76
 
69
77
  1 . Import the CSS file to set default styling.
70
78
 
71
- > :warning: If you are using a version before than `v5.13.0`, you must import the CSS file or the tooltip won't show!
79
+ > [!WARNING]\
80
+ > If you are using a version before than `v5.13.0`, you must import the CSS file or the tooltip won't show!
72
81
 
73
82
  ```js
74
83
  import 'react-tooltip/dist/react-tooltip.css'
@@ -100,6 +109,7 @@ import { Tooltip as ReactTooltip } from 'react-tooltip'
100
109
 
101
110
  4 . Include the `<Tooltip />` element.
102
111
 
112
+ > [!NOTE]\
103
113
  > Don't forget to set the id, it won't work without it!
104
114
 
105
115
  ```jsx
@@ -333,9 +333,9 @@ var styles = {"tooltip":"styles-module_tooltip__mnnfp","arrow":"styles-module_ar
333
333
 
334
334
  const Tooltip = ({
335
335
  // props
336
- id, className, classNameArrow, variant = 'dark', anchorId, anchorSelect, place = 'top', offset = 10, events = ['hover'], openOnClick = false, positionStrategy = 'absolute', middlewares, wrapper: WrapperElement, delayShow = 0, delayHide = 0, float = false, hidden = false, noArrow = false, clickable = false, closeOnEsc = false, closeOnScroll = false, closeOnResize = false, style: externalStyles, position, afterShow, afterHide,
336
+ id, className, classNameArrow, variant = 'dark', anchorId, anchorSelect, place = 'top', offset = 10, events = ['hover'], openOnClick = false, positionStrategy = 'absolute', middlewares, wrapper: WrapperElement, delayShow = 0, delayHide = 0, float = false, hidden = false, noArrow = false, clickable = false, closeOnEsc = false, closeOnScroll = false, closeOnResize = false, openEvents, closeEvents, globalCloseEvents, style: externalStyles, position, afterShow, afterHide,
337
337
  // props handled by controller
338
- content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAnchor, setActiveAnchor, border, opacity, arrowColor, }) => {
338
+ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, border, opacity, arrowColor, }) => {
339
339
  const tooltipRef = React.useRef(null);
340
340
  const tooltipArrowRef = React.useRef(null);
341
341
  const tooltipShowDelayTimerRef = React.useRef(null);
@@ -354,7 +354,48 @@ content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAncho
354
354
  const hoveringTooltip = React.useRef(false);
355
355
  const [anchorsBySelect, setAnchorsBySelect] = React.useState([]);
356
356
  const mounted = React.useRef(false);
357
+ /**
358
+ * @todo Update when deprecated stuff gets removed.
359
+ */
357
360
  const shouldOpenOnClick = openOnClick || events.includes('click');
361
+ const hasClickEvent = shouldOpenOnClick || (openEvents === null || openEvents === void 0 ? void 0 : openEvents.click) || (openEvents === null || openEvents === void 0 ? void 0 : openEvents.dblclick) || (openEvents === null || openEvents === void 0 ? void 0 : openEvents.mousedown);
362
+ const actualOpenEvents = openEvents
363
+ ? { ...openEvents }
364
+ : {
365
+ mouseenter: true,
366
+ focus: true,
367
+ click: false,
368
+ dblclick: false,
369
+ mousedown: false,
370
+ };
371
+ if (!openEvents && shouldOpenOnClick) {
372
+ Object.assign(actualOpenEvents, {
373
+ mouseenter: false,
374
+ focus: false,
375
+ click: true,
376
+ });
377
+ }
378
+ const actualCloseEvents = closeEvents
379
+ ? { ...closeEvents }
380
+ : {
381
+ mouseleave: true,
382
+ blur: true,
383
+ click: false,
384
+ };
385
+ if (!closeEvents && shouldOpenOnClick) {
386
+ Object.assign(actualCloseEvents, {
387
+ mouseleave: false,
388
+ blur: false,
389
+ });
390
+ }
391
+ const actualGlobalCloseEvents = globalCloseEvents
392
+ ? { ...globalCloseEvents }
393
+ : {
394
+ escape: closeOnEsc || false,
395
+ scroll: closeOnScroll || false,
396
+ resize: closeOnResize || false,
397
+ clickOutsideAnchor: hasClickEvent || false,
398
+ };
358
399
  /**
359
400
  * useLayoutEffect runs before useEffect,
360
401
  * but should be used carefully because of caveats
@@ -541,12 +582,6 @@ content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAncho
541
582
  handleTooltipPosition(mousePosition);
542
583
  lastFloatPosition.current = mousePosition;
543
584
  };
544
- const handleClickTooltipAnchor = (event) => {
545
- handleShowTooltip(event);
546
- if (delayHide) {
547
- handleHideTooltipDelayed();
548
- }
549
- };
550
585
  const handleClickOutsideAnchors = (event) => {
551
586
  var _a;
552
587
  const anchorById = document.querySelector(`[id='${anchorId}']`);
@@ -637,16 +672,16 @@ content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAncho
637
672
  };
638
673
  const anchorScrollParent = getScrollParent(activeAnchor);
639
674
  const tooltipScrollParent = getScrollParent(tooltipRef.current);
640
- if (closeOnScroll) {
675
+ if (actualGlobalCloseEvents.scroll) {
641
676
  window.addEventListener('scroll', handleScrollResize);
642
677
  anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.addEventListener('scroll', handleScrollResize);
643
678
  tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.addEventListener('scroll', handleScrollResize);
644
679
  }
645
680
  let updateTooltipCleanup = null;
646
- if (closeOnResize) {
681
+ if (actualGlobalCloseEvents.resize) {
647
682
  window.addEventListener('resize', handleScrollResize);
648
683
  }
649
- else if (activeAnchor && tooltipRef.current && !holdPositionOnRender) {
684
+ else if (activeAnchor && tooltipRef.current) {
650
685
  updateTooltipCleanup = dom.autoUpdate(activeAnchor, tooltipRef.current, updateTooltipPosition, {
651
686
  ancestorResize: true,
652
687
  elementResize: true,
@@ -659,22 +694,56 @@ content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAncho
659
694
  }
660
695
  handleShow(false);
661
696
  };
662
- if (closeOnEsc) {
697
+ if (actualGlobalCloseEvents.escape) {
663
698
  window.addEventListener('keydown', handleEsc);
664
699
  }
665
- const enabledEvents = [];
666
- if (shouldOpenOnClick) {
700
+ if (actualGlobalCloseEvents.clickOutsideAnchor) {
667
701
  window.addEventListener('click', handleClickOutsideAnchors);
668
- enabledEvents.push({ event: 'click', listener: handleClickTooltipAnchor });
669
702
  }
670
- else {
671
- enabledEvents.push({ event: 'mouseenter', listener: debouncedHandleShowTooltip }, { event: 'mouseleave', listener: debouncedHandleHideTooltip }, { event: 'focus', listener: debouncedHandleShowTooltip }, { event: 'blur', listener: debouncedHandleHideTooltip });
672
- if (float) {
673
- enabledEvents.push({
674
- event: 'mousemove',
675
- listener: handleMouseMove,
676
- });
703
+ const enabledEvents = [];
704
+ const handleClickOpenTooltipAnchor = (event) => {
705
+ if (show) {
706
+ return;
677
707
  }
708
+ handleShowTooltip(event);
709
+ };
710
+ const handleClickCloseTooltipAnchor = () => {
711
+ if (!show) {
712
+ return;
713
+ }
714
+ handleHideTooltip();
715
+ };
716
+ const regularEvents = ['mouseenter', 'mouseleave', 'focus', 'blur'];
717
+ const clickEvents = ['click', 'dblclick', 'mousedown', 'mouseup'];
718
+ Object.entries(actualOpenEvents).forEach(([event, enabled]) => {
719
+ if (!enabled) {
720
+ return;
721
+ }
722
+ if (regularEvents.includes(event)) {
723
+ enabledEvents.push({ event, listener: debouncedHandleShowTooltip });
724
+ }
725
+ else if (clickEvents.includes(event)) {
726
+ enabledEvents.push({ event, listener: handleClickOpenTooltipAnchor });
727
+ }
728
+ else ;
729
+ });
730
+ Object.entries(actualCloseEvents).forEach(([event, enabled]) => {
731
+ if (!enabled) {
732
+ return;
733
+ }
734
+ if (regularEvents.includes(event)) {
735
+ enabledEvents.push({ event, listener: debouncedHandleHideTooltip });
736
+ }
737
+ else if (clickEvents.includes(event)) {
738
+ enabledEvents.push({ event, listener: handleClickCloseTooltipAnchor });
739
+ }
740
+ else ;
741
+ });
742
+ if (float) {
743
+ enabledEvents.push({
744
+ event: 'mousemove',
745
+ listener: handleMouseMove,
746
+ });
678
747
  }
679
748
  const handleMouseEnterTooltip = () => {
680
749
  hoveringTooltip.current = true;
@@ -683,7 +752,9 @@ content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAncho
683
752
  hoveringTooltip.current = false;
684
753
  handleHideTooltip();
685
754
  };
686
- if (clickable && !shouldOpenOnClick) {
755
+ if (clickable && !hasClickEvent) {
756
+ // used to keep the tooltip open when hovering content.
757
+ // not needed if using click events.
687
758
  (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('mouseenter', handleMouseEnterTooltip);
688
759
  (_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.addEventListener('mouseleave', handleMouseLeaveTooltip);
689
760
  }
@@ -695,24 +766,24 @@ content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAncho
695
766
  });
696
767
  return () => {
697
768
  var _a, _b;
698
- if (closeOnScroll) {
769
+ if (actualGlobalCloseEvents.scroll) {
699
770
  window.removeEventListener('scroll', handleScrollResize);
700
771
  anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.removeEventListener('scroll', handleScrollResize);
701
772
  tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.removeEventListener('scroll', handleScrollResize);
702
773
  }
703
- if (closeOnResize) {
774
+ if (actualGlobalCloseEvents.resize) {
704
775
  window.removeEventListener('resize', handleScrollResize);
705
776
  }
706
777
  else {
707
778
  updateTooltipCleanup === null || updateTooltipCleanup === void 0 ? void 0 : updateTooltipCleanup();
708
779
  }
709
- if (shouldOpenOnClick) {
780
+ if (actualGlobalCloseEvents.clickOutsideAnchor) {
710
781
  window.removeEventListener('click', handleClickOutsideAnchors);
711
782
  }
712
- if (closeOnEsc) {
783
+ if (actualGlobalCloseEvents.escape) {
713
784
  window.removeEventListener('keydown', handleEsc);
714
785
  }
715
- if (clickable && !shouldOpenOnClick) {
786
+ if (clickable && !hasClickEvent) {
716
787
  (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('mouseenter', handleMouseEnterTooltip);
717
788
  (_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('mouseleave', handleMouseLeaveTooltip);
718
789
  }
@@ -733,8 +804,11 @@ content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAncho
733
804
  rendered,
734
805
  anchorRefs,
735
806
  anchorsBySelect,
736
- closeOnEsc,
737
- events,
807
+ // the effect uses the `actual*Events` objects, but this should work
808
+ openEvents,
809
+ closeEvents,
810
+ globalCloseEvents,
811
+ shouldOpenOnClick,
738
812
  ]);
739
813
  React.useEffect(() => {
740
814
  let selector = anchorSelect !== null && anchorSelect !== void 0 ? anchorSelect : '';
@@ -757,12 +831,20 @@ content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAncho
757
831
  if (activeAnchor) {
758
832
  const elements = [...mutation.removedNodes].filter((node) => node.nodeType === 1);
759
833
  if (selector) {
760
- removedAnchors.push(
761
- // the element itself is an anchor
762
- ...elements.filter((element) => element.matches(selector)));
763
- removedAnchors.push(
764
- // the element has children which are anchors
765
- ...elements.flatMap((element) => [...element.querySelectorAll(selector)]));
834
+ try {
835
+ removedAnchors.push(
836
+ // the element itself is an anchor
837
+ ...elements.filter((element) => element.matches(selector)));
838
+ removedAnchors.push(
839
+ // the element has children which are anchors
840
+ ...elements.flatMap((element) => [...element.querySelectorAll(selector)]));
841
+ }
842
+ catch (_a) {
843
+ /**
844
+ * invalid CSS selector.
845
+ * already warned on tooltip controller
846
+ */
847
+ }
766
848
  }
767
849
  elements.some((node) => {
768
850
  var _a;
@@ -793,14 +875,14 @@ content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAncho
793
875
  // the element has children which are anchors
794
876
  ...elements.flatMap((element) => [...element.querySelectorAll(selector)]));
795
877
  }
796
- catch (_a) {
878
+ catch (_b) {
797
879
  /**
798
880
  * invalid CSS selector.
799
881
  * already warned on tooltip controller
800
882
  */
801
883
  }
802
884
  });
803
- if (newAnchors.length) {
885
+ if (newAnchors.length || removedAnchors.length) {
804
886
  setAnchorsBySelect((anchors) => [
805
887
  ...anchors.filter((anchor) => removedAnchors.includes(anchor)),
806
888
  ...newAnchors,
@@ -875,7 +957,7 @@ content, contentWrapperRef, isOpen, holdPositionOnRender, setIsOpen, activeAncho
875
957
  }
876
958
  }, [id, anchorSelect]);
877
959
  const canShow = !hidden && content && show && Object.keys(inlineStyles).length > 0;
878
- return rendered || (wasShowing.current && holdPositionOnRender) ? (React__default["default"].createElement(WrapperElement, { id: id, role: "tooltip", className: classNames__default["default"]('react-tooltip', coreStyles['tooltip'], styles['tooltip'], styles[variant], className, `react-tooltip__place-${actualPlacement}`, {
960
+ return rendered ? (React__default["default"].createElement(WrapperElement, { id: id, role: "tooltip", className: classNames__default["default"]('react-tooltip', coreStyles['tooltip'], styles['tooltip'], styles[variant], className, `react-tooltip__place-${actualPlacement}`, {
879
961
  'react-tooltip__show': canShow,
880
962
  [coreStyles['show']]: canShow,
881
963
  [coreStyles['fixed']]: positionStrategy === 'fixed',
@@ -905,7 +987,7 @@ const TooltipContent = ({ content }) => {
905
987
  return React__default["default"].createElement("span", { dangerouslySetInnerHTML: { __html: content } });
906
988
  };
907
989
 
908
- const TooltipController = ({ id, anchorId, anchorSelect, content, html, render, className, classNameArrow, variant = 'dark', place = 'top', offset = 10, wrapper = 'div', children = null, events = ['hover'], openOnClick = false, positionStrategy = 'absolute', middlewares, delayShow = 0, delayHide = 0, float = false, hidden = false, noArrow = false, clickable = false, closeOnEsc = false, closeOnScroll = false, closeOnResize = false, style, position, isOpen, disableStyleInjection = false, holdPositionOnRender, border, opacity, arrowColor, setIsOpen, afterShow, afterHide, }) => {
990
+ const TooltipController = ({ id, anchorId, anchorSelect, content, html, render, className, classNameArrow, variant = 'dark', place = 'top', offset = 10, wrapper = 'div', children = null, events = ['hover'], openOnClick = false, positionStrategy = 'absolute', middlewares, delayShow = 0, delayHide = 0, float = false, hidden = false, noArrow = false, clickable = false, closeOnEsc = false, closeOnScroll = false, closeOnResize = false, openEvents, closeEvents, globalCloseEvents, style, position, isOpen, disableStyleInjection = false, border, opacity, arrowColor, setIsOpen, afterShow, afterHide, }) => {
909
991
  const [tooltipContent, setTooltipContent] = React.useState(content);
910
992
  const [tooltipHtml, setTooltipHtml] = React.useState(html);
911
993
  const [tooltipPlace, setTooltipPlace] = React.useState(place);
@@ -1153,10 +1235,12 @@ const TooltipController = ({ id, anchorId, anchorSelect, content, html, render,
1153
1235
  closeOnEsc,
1154
1236
  closeOnScroll,
1155
1237
  closeOnResize,
1238
+ openEvents,
1239
+ closeEvents,
1240
+ globalCloseEvents,
1156
1241
  style,
1157
1242
  position,
1158
1243
  isOpen,
1159
- holdPositionOnRender,
1160
1244
  border,
1161
1245
  opacity,
1162
1246
  arrowColor,