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.
@@ -331,9 +331,10 @@
331
331
 
332
332
  const Tooltip = ({
333
333
  // props
334
- 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,
334
+ 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,
335
335
  // props handled by controller
336
336
  content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, border, opacity, arrowColor, }) => {
337
+ var _a;
337
338
  const tooltipRef = React.useRef(null);
338
339
  const tooltipArrowRef = React.useRef(null);
339
340
  const tooltipShowDelayTimerRef = React.useRef(null);
@@ -343,6 +344,7 @@
343
344
  const [inlineArrowStyles, setInlineArrowStyles] = React.useState({});
344
345
  const [show, setShow] = React.useState(false);
345
346
  const [rendered, setRendered] = React.useState(false);
347
+ const [imperativeOptions, setImperativeOptions] = React.useState(null);
346
348
  const wasShowing = React.useRef(false);
347
349
  const lastFloatPosition = React.useRef(null);
348
350
  /**
@@ -352,48 +354,7 @@
352
354
  const hoveringTooltip = React.useRef(false);
353
355
  const [anchorsBySelect, setAnchorsBySelect] = React.useState([]);
354
356
  const mounted = React.useRef(false);
355
- /**
356
- * @todo Update when deprecated stuff gets removed.
357
- */
358
357
  const shouldOpenOnClick = openOnClick || events.includes('click');
359
- 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);
360
- const actualOpenEvents = openEvents
361
- ? { ...openEvents }
362
- : {
363
- mouseenter: true,
364
- focus: true,
365
- click: false,
366
- dblclick: false,
367
- mousedown: false,
368
- };
369
- if (!openEvents && shouldOpenOnClick) {
370
- Object.assign(actualOpenEvents, {
371
- mouseenter: false,
372
- focus: false,
373
- click: true,
374
- });
375
- }
376
- const actualCloseEvents = closeEvents
377
- ? { ...closeEvents }
378
- : {
379
- mouseleave: true,
380
- blur: true,
381
- click: false,
382
- };
383
- if (!closeEvents && shouldOpenOnClick) {
384
- Object.assign(actualCloseEvents, {
385
- mouseleave: false,
386
- blur: false,
387
- });
388
- }
389
- const actualGlobalCloseEvents = globalCloseEvents
390
- ? { ...globalCloseEvents }
391
- : {
392
- escape: closeOnEsc || false,
393
- scroll: closeOnScroll || false,
394
- resize: closeOnResize || false,
395
- clickOutsideAnchor: hasClickEvent || false,
396
- };
397
358
  /**
398
359
  * useLayoutEffect runs before useEffect,
399
360
  * but should be used carefully because of caveats
@@ -470,6 +431,7 @@
470
431
  afterShow === null || afterShow === void 0 ? void 0 : afterShow();
471
432
  }
472
433
  else {
434
+ setImperativeOptions(null);
473
435
  afterHide === null || afterHide === void 0 ? void 0 : afterHide();
474
436
  }
475
437
  }, [show]);
@@ -580,8 +542,17 @@
580
542
  handleTooltipPosition(mousePosition);
581
543
  lastFloatPosition.current = mousePosition;
582
544
  };
545
+ const handleClickTooltipAnchor = (event) => {
546
+ handleShowTooltip(event);
547
+ if (delayHide) {
548
+ handleHideTooltipDelayed();
549
+ }
550
+ };
583
551
  const handleClickOutsideAnchors = (event) => {
584
552
  var _a;
553
+ if (!show) {
554
+ return;
555
+ }
585
556
  const anchorById = document.querySelector(`[id='${anchorId}']`);
586
557
  const anchors = [anchorById, ...anchorsBySelect];
587
558
  if (anchors.some((anchor) => anchor === null || anchor === void 0 ? void 0 : anchor.contains(event.target))) {
@@ -600,9 +571,11 @@
600
571
  const debouncedHandleShowTooltip = debounce(handleShowTooltip, 50, true);
601
572
  const debouncedHandleHideTooltip = debounce(handleHideTooltip, 50, true);
602
573
  const updateTooltipPosition = React.useCallback(() => {
603
- if (position) {
574
+ var _a;
575
+ const actualPosition = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.position) !== null && _a !== void 0 ? _a : position;
576
+ if (actualPosition) {
604
577
  // if `position` is set, override regular and `float` positioning
605
- handleTooltipPosition(position);
578
+ handleTooltipPosition(actualPosition);
606
579
  return;
607
580
  }
608
581
  if (float) {
@@ -653,6 +626,7 @@
653
626
  offset,
654
627
  positionStrategy,
655
628
  position,
629
+ imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.position,
656
630
  float,
657
631
  ]);
658
632
  React.useEffect(() => {
@@ -670,13 +644,13 @@
670
644
  };
671
645
  const anchorScrollParent = getScrollParent(activeAnchor);
672
646
  const tooltipScrollParent = getScrollParent(tooltipRef.current);
673
- if (actualGlobalCloseEvents.scroll) {
647
+ if (closeOnScroll) {
674
648
  window.addEventListener('scroll', handleScrollResize);
675
649
  anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.addEventListener('scroll', handleScrollResize);
676
650
  tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.addEventListener('scroll', handleScrollResize);
677
651
  }
678
652
  let updateTooltipCleanup = null;
679
- if (actualGlobalCloseEvents.resize) {
653
+ if (closeOnResize) {
680
654
  window.addEventListener('resize', handleScrollResize);
681
655
  }
682
656
  else if (activeAnchor && tooltipRef.current) {
@@ -692,56 +666,22 @@
692
666
  }
693
667
  handleShow(false);
694
668
  };
695
- if (actualGlobalCloseEvents.escape) {
669
+ if (closeOnEsc) {
696
670
  window.addEventListener('keydown', handleEsc);
697
671
  }
698
- if (actualGlobalCloseEvents.clickOutsideAnchor) {
672
+ const enabledEvents = [];
673
+ if (shouldOpenOnClick) {
699
674
  window.addEventListener('click', handleClickOutsideAnchors);
675
+ enabledEvents.push({ event: 'click', listener: handleClickTooltipAnchor });
700
676
  }
701
- const enabledEvents = [];
702
- const handleClickOpenTooltipAnchor = (event) => {
703
- if (show) {
704
- return;
705
- }
706
- handleShowTooltip(event);
707
- };
708
- const handleClickCloseTooltipAnchor = () => {
709
- if (!show) {
710
- return;
711
- }
712
- handleHideTooltip();
713
- };
714
- const regularEvents = ['mouseenter', 'mouseleave', 'focus', 'blur'];
715
- const clickEvents = ['click', 'dblclick', 'mousedown', 'mouseup'];
716
- Object.entries(actualOpenEvents).forEach(([event, enabled]) => {
717
- if (!enabled) {
718
- return;
719
- }
720
- if (regularEvents.includes(event)) {
721
- enabledEvents.push({ event, listener: debouncedHandleShowTooltip });
722
- }
723
- else if (clickEvents.includes(event)) {
724
- enabledEvents.push({ event, listener: handleClickOpenTooltipAnchor });
725
- }
726
- else ;
727
- });
728
- Object.entries(actualCloseEvents).forEach(([event, enabled]) => {
729
- if (!enabled) {
730
- return;
731
- }
732
- if (regularEvents.includes(event)) {
733
- enabledEvents.push({ event, listener: debouncedHandleHideTooltip });
734
- }
735
- else if (clickEvents.includes(event)) {
736
- enabledEvents.push({ event, listener: handleClickCloseTooltipAnchor });
677
+ else {
678
+ enabledEvents.push({ event: 'mouseenter', listener: debouncedHandleShowTooltip }, { event: 'mouseleave', listener: debouncedHandleHideTooltip }, { event: 'focus', listener: debouncedHandleShowTooltip }, { event: 'blur', listener: debouncedHandleHideTooltip });
679
+ if (float) {
680
+ enabledEvents.push({
681
+ event: 'mousemove',
682
+ listener: handleMouseMove,
683
+ });
737
684
  }
738
- else ;
739
- });
740
- if (float) {
741
- enabledEvents.push({
742
- event: 'mousemove',
743
- listener: handleMouseMove,
744
- });
745
685
  }
746
686
  const handleMouseEnterTooltip = () => {
747
687
  hoveringTooltip.current = true;
@@ -750,9 +690,7 @@
750
690
  hoveringTooltip.current = false;
751
691
  handleHideTooltip();
752
692
  };
753
- if (clickable && !hasClickEvent) {
754
- // used to keep the tooltip open when hovering content.
755
- // not needed if using click events.
693
+ if (clickable && !shouldOpenOnClick) {
756
694
  (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('mouseenter', handleMouseEnterTooltip);
757
695
  (_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.addEventListener('mouseleave', handleMouseLeaveTooltip);
758
696
  }
@@ -764,24 +702,24 @@
764
702
  });
765
703
  return () => {
766
704
  var _a, _b;
767
- if (actualGlobalCloseEvents.scroll) {
705
+ if (closeOnScroll) {
768
706
  window.removeEventListener('scroll', handleScrollResize);
769
707
  anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.removeEventListener('scroll', handleScrollResize);
770
708
  tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.removeEventListener('scroll', handleScrollResize);
771
709
  }
772
- if (actualGlobalCloseEvents.resize) {
710
+ if (closeOnResize) {
773
711
  window.removeEventListener('resize', handleScrollResize);
774
712
  }
775
713
  else {
776
714
  updateTooltipCleanup === null || updateTooltipCleanup === void 0 ? void 0 : updateTooltipCleanup();
777
715
  }
778
- if (actualGlobalCloseEvents.clickOutsideAnchor) {
716
+ if (shouldOpenOnClick) {
779
717
  window.removeEventListener('click', handleClickOutsideAnchors);
780
718
  }
781
- if (actualGlobalCloseEvents.escape) {
719
+ if (closeOnEsc) {
782
720
  window.removeEventListener('keydown', handleEsc);
783
721
  }
784
- if (clickable && !hasClickEvent) {
722
+ if (clickable && !shouldOpenOnClick) {
785
723
  (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('mouseenter', handleMouseEnterTooltip);
786
724
  (_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('mouseleave', handleMouseLeaveTooltip);
787
725
  }
@@ -802,14 +740,12 @@
802
740
  rendered,
803
741
  anchorRefs,
804
742
  anchorsBySelect,
805
- // the effect uses the `actual*Events` objects, but this should work
806
- openEvents,
807
- closeEvents,
808
- globalCloseEvents,
809
- shouldOpenOnClick,
743
+ closeOnEsc,
744
+ events,
810
745
  ]);
811
746
  React.useEffect(() => {
812
- let selector = anchorSelect !== null && anchorSelect !== void 0 ? anchorSelect : '';
747
+ var _a, _b;
748
+ let selector = (_b = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect) !== null && _a !== void 0 ? _a : anchorSelect) !== null && _b !== void 0 ? _b : '';
813
749
  if (!selector && id) {
814
750
  selector = `[data-tooltip-id='${id}']`;
815
751
  }
@@ -898,7 +834,7 @@
898
834
  return () => {
899
835
  documentObserver.disconnect();
900
836
  };
901
- }, [id, anchorSelect, activeAnchor]);
837
+ }, [id, anchorSelect, imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect, activeAnchor]);
902
838
  React.useEffect(() => {
903
839
  updateTooltipPosition();
904
840
  }, [updateTooltipPosition]);
@@ -938,7 +874,8 @@
938
874
  };
939
875
  }, []);
940
876
  React.useEffect(() => {
941
- let selector = anchorSelect;
877
+ var _a;
878
+ let selector = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect) !== null && _a !== void 0 ? _a : anchorSelect;
942
879
  if (!selector && id) {
943
880
  selector = `[data-tooltip-id='${id}']`;
944
881
  }
@@ -949,12 +886,37 @@
949
886
  const anchors = Array.from(document.querySelectorAll(selector));
950
887
  setAnchorsBySelect(anchors);
951
888
  }
952
- catch (_a) {
889
+ catch (_b) {
953
890
  // warning was already issued in the controller
954
891
  setAnchorsBySelect([]);
955
892
  }
956
- }, [id, anchorSelect]);
957
- const canShow = !hidden && content && show && Object.keys(inlineStyles).length > 0;
893
+ }, [id, anchorSelect, imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect]);
894
+ const actualContent = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.content) !== null && _a !== void 0 ? _a : content;
895
+ const canShow = Boolean(!hidden && actualContent && show && Object.keys(inlineStyles).length > 0);
896
+ React.useImperativeHandle(forwardRef, () => ({
897
+ open: (options) => {
898
+ if (options === null || options === void 0 ? void 0 : options.anchorSelect) {
899
+ try {
900
+ document.querySelector(options.anchorSelect);
901
+ }
902
+ catch (_a) {
903
+ {
904
+ // eslint-disable-next-line no-console
905
+ console.warn(`[react-tooltip] "${options.anchorSelect}" is not a valid CSS selector`);
906
+ }
907
+ return;
908
+ }
909
+ }
910
+ setImperativeOptions(options !== null && options !== void 0 ? options : null);
911
+ handleShow(true);
912
+ },
913
+ close: () => {
914
+ handleShow(false);
915
+ },
916
+ activeAnchor,
917
+ place: actualPlacement,
918
+ isOpen: rendered && canShow,
919
+ }));
958
920
  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}`, {
959
921
  'react-tooltip__show': canShow,
960
922
  [coreStyles['show']]: canShow,
@@ -965,7 +927,7 @@
965
927
  ...inlineStyles,
966
928
  opacity: opacity !== undefined && canShow ? opacity : undefined,
967
929
  }, ref: tooltipRef },
968
- content,
930
+ actualContent,
969
931
  React__default["default"].createElement(WrapperElement, { className: classNames__default["default"]('react-tooltip-arrow', coreStyles['arrow'], styles['arrow'], classNameArrow, {
970
932
  /**
971
933
  * changed from dash `no-arrow` to camelcase because of:
@@ -985,7 +947,7 @@
985
947
  return React__default["default"].createElement("span", { dangerouslySetInnerHTML: { __html: content } });
986
948
  };
987
949
 
988
- 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, }) => {
950
+ const TooltipController = React__default["default"].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) => {
989
951
  const [tooltipContent, setTooltipContent] = React.useState(content);
990
952
  const [tooltipHtml, setTooltipHtml] = React.useState(html);
991
953
  const [tooltipPlace, setTooltipPlace] = React.useState(place);
@@ -1209,6 +1171,7 @@
1209
1171
  renderedContent = React__default["default"].createElement(TooltipContent, { content: tooltipHtml });
1210
1172
  }
1211
1173
  const props = {
1174
+ forwardRef: ref,
1212
1175
  id,
1213
1176
  anchorId,
1214
1177
  anchorSelect,
@@ -1233,9 +1196,6 @@
1233
1196
  closeOnEsc,
1234
1197
  closeOnScroll,
1235
1198
  closeOnResize,
1236
- openEvents,
1237
- closeEvents,
1238
- globalCloseEvents,
1239
1199
  style,
1240
1200
  position,
1241
1201
  isOpen,
@@ -1249,7 +1209,7 @@
1249
1209
  setActiveAnchor: (anchor) => setActiveAnchor(anchor),
1250
1210
  };
1251
1211
  return React__default["default"].createElement(Tooltip, { ...props });
1252
- };
1212
+ });
1253
1213
 
1254
1214
  // those content will be replaced in build time with the `react-tooltip.css` builded content
1255
1215
  const TooltipCoreStyles = `:root {