react-tooltip 5.22.0-beta.1108.0 → 5.22.0-beta.1109.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.
@@ -5,7 +5,7 @@
5
5
  * @copyright ReactTooltip Team
6
6
  * @license MIT
7
7
  */
8
- import React, { createContext, useState, useCallback, useMemo, useContext, useRef, useEffect, useLayoutEffect } from 'react';
8
+ import React, { createContext, useState, useCallback, useMemo, useContext, useRef, useEffect, useLayoutEffect, useImperativeHandle } from 'react';
9
9
  import { arrow, computePosition, offset, flip, shift, autoUpdate } from '@floating-ui/dom';
10
10
  import classNames from 'classnames';
11
11
 
@@ -324,9 +324,10 @@ var styles = {"tooltip":"styles-module_tooltip__mnnfp","arrow":"styles-module_ar
324
324
 
325
325
  const Tooltip = ({
326
326
  // props
327
- 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,
327
+ forwardRef, 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,
328
328
  // props handled by controller
329
329
  content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, border, opacity, arrowColor, }) => {
330
+ var _a;
330
331
  const tooltipRef = useRef(null);
331
332
  const tooltipArrowRef = useRef(null);
332
333
  const tooltipShowDelayTimerRef = useRef(null);
@@ -336,6 +337,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
336
337
  const [inlineArrowStyles, setInlineArrowStyles] = useState({});
337
338
  const [show, setShow] = useState(false);
338
339
  const [rendered, setRendered] = useState(false);
340
+ const [imperativeOptions, setImperativeOptions] = useState(null);
339
341
  const wasShowing = useRef(false);
340
342
  const lastFloatPosition = useRef(null);
341
343
  /**
@@ -345,48 +347,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
345
347
  const hoveringTooltip = useRef(false);
346
348
  const [anchorsBySelect, setAnchorsBySelect] = useState([]);
347
349
  const mounted = useRef(false);
348
- /**
349
- * @todo Update when deprecated stuff gets removed.
350
- */
351
350
  const shouldOpenOnClick = openOnClick || events.includes('click');
352
- 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);
353
- const actualOpenEvents = openEvents
354
- ? { ...openEvents }
355
- : {
356
- mouseenter: true,
357
- focus: true,
358
- click: false,
359
- dblclick: false,
360
- mousedown: false,
361
- };
362
- if (!openEvents && shouldOpenOnClick) {
363
- Object.assign(actualOpenEvents, {
364
- mouseenter: false,
365
- focus: false,
366
- click: true,
367
- });
368
- }
369
- const actualCloseEvents = closeEvents
370
- ? { ...closeEvents }
371
- : {
372
- mouseleave: true,
373
- blur: true,
374
- click: false,
375
- };
376
- if (!closeEvents && shouldOpenOnClick) {
377
- Object.assign(actualCloseEvents, {
378
- mouseleave: false,
379
- blur: false,
380
- });
381
- }
382
- const actualGlobalCloseEvents = globalCloseEvents
383
- ? { ...globalCloseEvents }
384
- : {
385
- escape: closeOnEsc || false,
386
- scroll: closeOnScroll || false,
387
- resize: closeOnResize || false,
388
- clickOutsideAnchor: hasClickEvent || false,
389
- };
390
351
  /**
391
352
  * useLayoutEffect runs before useEffect,
392
353
  * but should be used carefully because of caveats
@@ -463,6 +424,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
463
424
  afterShow === null || afterShow === void 0 ? void 0 : afterShow();
464
425
  }
465
426
  else {
427
+ setImperativeOptions(null);
466
428
  afterHide === null || afterHide === void 0 ? void 0 : afterHide();
467
429
  }
468
430
  }, [show]);
@@ -573,8 +535,17 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
573
535
  handleTooltipPosition(mousePosition);
574
536
  lastFloatPosition.current = mousePosition;
575
537
  };
538
+ const handleClickTooltipAnchor = (event) => {
539
+ handleShowTooltip(event);
540
+ if (delayHide) {
541
+ handleHideTooltipDelayed();
542
+ }
543
+ };
576
544
  const handleClickOutsideAnchors = (event) => {
577
545
  var _a;
546
+ if (!show) {
547
+ return;
548
+ }
578
549
  const anchorById = document.querySelector(`[id='${anchorId}']`);
579
550
  const anchors = [anchorById, ...anchorsBySelect];
580
551
  if (anchors.some((anchor) => anchor === null || anchor === void 0 ? void 0 : anchor.contains(event.target))) {
@@ -593,9 +564,11 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
593
564
  const debouncedHandleShowTooltip = debounce(handleShowTooltip, 50, true);
594
565
  const debouncedHandleHideTooltip = debounce(handleHideTooltip, 50, true);
595
566
  const updateTooltipPosition = useCallback(() => {
596
- if (position) {
567
+ var _a;
568
+ const actualPosition = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.position) !== null && _a !== void 0 ? _a : position;
569
+ if (actualPosition) {
597
570
  // if `position` is set, override regular and `float` positioning
598
- handleTooltipPosition(position);
571
+ handleTooltipPosition(actualPosition);
599
572
  return;
600
573
  }
601
574
  if (float) {
@@ -646,6 +619,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
646
619
  offset,
647
620
  positionStrategy,
648
621
  position,
622
+ imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.position,
649
623
  float,
650
624
  ]);
651
625
  useEffect(() => {
@@ -663,13 +637,13 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
663
637
  };
664
638
  const anchorScrollParent = getScrollParent(activeAnchor);
665
639
  const tooltipScrollParent = getScrollParent(tooltipRef.current);
666
- if (actualGlobalCloseEvents.scroll) {
640
+ if (closeOnScroll) {
667
641
  window.addEventListener('scroll', handleScrollResize);
668
642
  anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.addEventListener('scroll', handleScrollResize);
669
643
  tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.addEventListener('scroll', handleScrollResize);
670
644
  }
671
645
  let updateTooltipCleanup = null;
672
- if (actualGlobalCloseEvents.resize) {
646
+ if (closeOnResize) {
673
647
  window.addEventListener('resize', handleScrollResize);
674
648
  }
675
649
  else if (activeAnchor && tooltipRef.current) {
@@ -685,56 +659,22 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
685
659
  }
686
660
  handleShow(false);
687
661
  };
688
- if (actualGlobalCloseEvents.escape) {
662
+ if (closeOnEsc) {
689
663
  window.addEventListener('keydown', handleEsc);
690
664
  }
691
- if (actualGlobalCloseEvents.clickOutsideAnchor) {
665
+ const enabledEvents = [];
666
+ if (shouldOpenOnClick) {
692
667
  window.addEventListener('click', handleClickOutsideAnchors);
668
+ enabledEvents.push({ event: 'click', listener: handleClickTooltipAnchor });
693
669
  }
694
- const enabledEvents = [];
695
- const handleClickOpenTooltipAnchor = (event) => {
696
- if (show) {
697
- return;
698
- }
699
- handleShowTooltip(event);
700
- };
701
- const handleClickCloseTooltipAnchor = () => {
702
- if (!show) {
703
- return;
704
- }
705
- handleHideTooltip();
706
- };
707
- const regularEvents = ['mouseenter', 'mouseleave', 'focus', 'blur'];
708
- const clickEvents = ['click', 'dblclick', 'mousedown', 'mouseup'];
709
- Object.entries(actualOpenEvents).forEach(([event, enabled]) => {
710
- if (!enabled) {
711
- return;
712
- }
713
- if (regularEvents.includes(event)) {
714
- enabledEvents.push({ event, listener: debouncedHandleShowTooltip });
715
- }
716
- else if (clickEvents.includes(event)) {
717
- enabledEvents.push({ event, listener: handleClickOpenTooltipAnchor });
718
- }
719
- else ;
720
- });
721
- Object.entries(actualCloseEvents).forEach(([event, enabled]) => {
722
- if (!enabled) {
723
- return;
724
- }
725
- if (regularEvents.includes(event)) {
726
- enabledEvents.push({ event, listener: debouncedHandleHideTooltip });
727
- }
728
- else if (clickEvents.includes(event)) {
729
- enabledEvents.push({ event, listener: handleClickCloseTooltipAnchor });
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
+ });
730
677
  }
731
- else ;
732
- });
733
- if (float) {
734
- enabledEvents.push({
735
- event: 'mousemove',
736
- listener: handleMouseMove,
737
- });
738
678
  }
739
679
  const handleMouseEnterTooltip = () => {
740
680
  hoveringTooltip.current = true;
@@ -743,9 +683,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
743
683
  hoveringTooltip.current = false;
744
684
  handleHideTooltip();
745
685
  };
746
- if (clickable && !hasClickEvent) {
747
- // used to keep the tooltip open when hovering content.
748
- // not needed if using click events.
686
+ if (clickable && !shouldOpenOnClick) {
749
687
  (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('mouseenter', handleMouseEnterTooltip);
750
688
  (_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.addEventListener('mouseleave', handleMouseLeaveTooltip);
751
689
  }
@@ -757,24 +695,24 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
757
695
  });
758
696
  return () => {
759
697
  var _a, _b;
760
- if (actualGlobalCloseEvents.scroll) {
698
+ if (closeOnScroll) {
761
699
  window.removeEventListener('scroll', handleScrollResize);
762
700
  anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.removeEventListener('scroll', handleScrollResize);
763
701
  tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.removeEventListener('scroll', handleScrollResize);
764
702
  }
765
- if (actualGlobalCloseEvents.resize) {
703
+ if (closeOnResize) {
766
704
  window.removeEventListener('resize', handleScrollResize);
767
705
  }
768
706
  else {
769
707
  updateTooltipCleanup === null || updateTooltipCleanup === void 0 ? void 0 : updateTooltipCleanup();
770
708
  }
771
- if (actualGlobalCloseEvents.clickOutsideAnchor) {
709
+ if (shouldOpenOnClick) {
772
710
  window.removeEventListener('click', handleClickOutsideAnchors);
773
711
  }
774
- if (actualGlobalCloseEvents.escape) {
712
+ if (closeOnEsc) {
775
713
  window.removeEventListener('keydown', handleEsc);
776
714
  }
777
- if (clickable && !hasClickEvent) {
715
+ if (clickable && !shouldOpenOnClick) {
778
716
  (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('mouseenter', handleMouseEnterTooltip);
779
717
  (_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('mouseleave', handleMouseLeaveTooltip);
780
718
  }
@@ -795,14 +733,12 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
795
733
  rendered,
796
734
  anchorRefs,
797
735
  anchorsBySelect,
798
- // the effect uses the `actual*Events` objects, but this should work
799
- openEvents,
800
- closeEvents,
801
- globalCloseEvents,
802
- shouldOpenOnClick,
736
+ closeOnEsc,
737
+ events,
803
738
  ]);
804
739
  useEffect(() => {
805
- let selector = anchorSelect !== null && anchorSelect !== void 0 ? anchorSelect : '';
740
+ var _a, _b;
741
+ let selector = (_b = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect) !== null && _a !== void 0 ? _a : anchorSelect) !== null && _b !== void 0 ? _b : '';
806
742
  if (!selector && id) {
807
743
  selector = `[data-tooltip-id='${id}']`;
808
744
  }
@@ -891,7 +827,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
891
827
  return () => {
892
828
  documentObserver.disconnect();
893
829
  };
894
- }, [id, anchorSelect, activeAnchor]);
830
+ }, [id, anchorSelect, imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect, activeAnchor]);
895
831
  useEffect(() => {
896
832
  updateTooltipPosition();
897
833
  }, [updateTooltipPosition]);
@@ -931,7 +867,8 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
931
867
  };
932
868
  }, []);
933
869
  useEffect(() => {
934
- let selector = anchorSelect;
870
+ var _a;
871
+ let selector = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect) !== null && _a !== void 0 ? _a : anchorSelect;
935
872
  if (!selector && id) {
936
873
  selector = `[data-tooltip-id='${id}']`;
937
874
  }
@@ -942,12 +879,37 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
942
879
  const anchors = Array.from(document.querySelectorAll(selector));
943
880
  setAnchorsBySelect(anchors);
944
881
  }
945
- catch (_a) {
882
+ catch (_b) {
946
883
  // warning was already issued in the controller
947
884
  setAnchorsBySelect([]);
948
885
  }
949
- }, [id, anchorSelect]);
950
- const canShow = !hidden && content && show && Object.keys(inlineStyles).length > 0;
886
+ }, [id, anchorSelect, imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect]);
887
+ const actualContent = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.content) !== null && _a !== void 0 ? _a : content;
888
+ const canShow = Boolean(!hidden && actualContent && show && Object.keys(inlineStyles).length > 0);
889
+ useImperativeHandle(forwardRef, () => ({
890
+ open: (options) => {
891
+ if (options === null || options === void 0 ? void 0 : options.anchorSelect) {
892
+ try {
893
+ document.querySelector(options.anchorSelect);
894
+ }
895
+ catch (_a) {
896
+ {
897
+ // eslint-disable-next-line no-console
898
+ console.warn(`[react-tooltip] "${options.anchorSelect}" is not a valid CSS selector`);
899
+ }
900
+ return;
901
+ }
902
+ }
903
+ setImperativeOptions(options !== null && options !== void 0 ? options : null);
904
+ handleShow(true);
905
+ },
906
+ close: () => {
907
+ handleShow(false);
908
+ },
909
+ activeAnchor,
910
+ place: actualPlacement,
911
+ isOpen: rendered && canShow,
912
+ }));
951
913
  return rendered ? (React.createElement(WrapperElement, { id: id, role: "tooltip", className: classNames('react-tooltip', coreStyles['tooltip'], styles['tooltip'], styles[variant], className, `react-tooltip__place-${actualPlacement}`, {
952
914
  'react-tooltip__show': canShow,
953
915
  [coreStyles['show']]: canShow,
@@ -958,7 +920,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
958
920
  ...inlineStyles,
959
921
  opacity: opacity !== undefined && canShow ? opacity : undefined,
960
922
  }, ref: tooltipRef },
961
- content,
923
+ actualContent,
962
924
  React.createElement(WrapperElement, { className: classNames('react-tooltip-arrow', coreStyles['arrow'], styles['arrow'], classNameArrow, {
963
925
  /**
964
926
  * changed from dash `no-arrow` to camelcase because of:
@@ -978,7 +940,7 @@ const TooltipContent = ({ content }) => {
978
940
  return React.createElement("span", { dangerouslySetInnerHTML: { __html: content } });
979
941
  };
980
942
 
981
- 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, }) => {
943
+ const TooltipController = React.forwardRef(({ 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, border, opacity, arrowColor, setIsOpen, afterShow, afterHide, }, ref) => {
982
944
  const [tooltipContent, setTooltipContent] = useState(content);
983
945
  const [tooltipHtml, setTooltipHtml] = useState(html);
984
946
  const [tooltipPlace, setTooltipPlace] = useState(place);
@@ -1202,6 +1164,7 @@ const TooltipController = ({ id, anchorId, anchorSelect, content, html, render,
1202
1164
  renderedContent = React.createElement(TooltipContent, { content: tooltipHtml });
1203
1165
  }
1204
1166
  const props = {
1167
+ forwardRef: ref,
1205
1168
  id,
1206
1169
  anchorId,
1207
1170
  anchorSelect,
@@ -1226,9 +1189,6 @@ const TooltipController = ({ id, anchorId, anchorSelect, content, html, render,
1226
1189
  closeOnEsc,
1227
1190
  closeOnScroll,
1228
1191
  closeOnResize,
1229
- openEvents,
1230
- closeEvents,
1231
- globalCloseEvents,
1232
1192
  style,
1233
1193
  position,
1234
1194
  isOpen,
@@ -1242,7 +1202,7 @@ const TooltipController = ({ id, anchorId, anchorSelect, content, html, render,
1242
1202
  setActiveAnchor: (anchor) => setActiveAnchor(anchor),
1243
1203
  };
1244
1204
  return React.createElement(Tooltip, { ...props });
1245
- };
1205
+ });
1246
1206
 
1247
1207
  // those content will be replaced in build time with the `react-tooltip.css` builded content
1248
1208
  const TooltipCoreStyles = `:root {