react-tooltip 5.22.0 → 5.23.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, openEvents, closeEvents, globalCloseEvents, imperativeModeOnly, 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
  /**
@@ -372,6 +374,8 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
372
374
  mouseleave: true,
373
375
  blur: true,
374
376
  click: false,
377
+ dblclick: false,
378
+ mouseup: false,
375
379
  };
376
380
  if (!closeEvents && shouldOpenOnClick) {
377
381
  Object.assign(actualCloseEvents, {
@@ -387,6 +391,28 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
387
391
  resize: closeOnResize || false,
388
392
  clickOutsideAnchor: hasClickEvent || false,
389
393
  };
394
+ if (imperativeModeOnly) {
395
+ Object.assign(actualOpenEvents, {
396
+ mouseenter: false,
397
+ focus: false,
398
+ click: false,
399
+ dblclick: false,
400
+ mousedown: false,
401
+ });
402
+ Object.assign(actualCloseEvents, {
403
+ mouseleave: false,
404
+ blur: false,
405
+ click: false,
406
+ dblclick: false,
407
+ mouseup: false,
408
+ });
409
+ Object.assign(actualGlobalCloseEvents, {
410
+ escape: false,
411
+ scroll: false,
412
+ resize: false,
413
+ clickOutsideAnchor: false,
414
+ });
415
+ }
390
416
  /**
391
417
  * useLayoutEffect runs before useEffect,
392
418
  * but should be used carefully because of caveats
@@ -445,17 +471,14 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
445
471
  if (show) {
446
472
  afterShow === null || afterShow === void 0 ? void 0 : afterShow();
447
473
  }
448
- else {
449
- afterHide === null || afterHide === void 0 ? void 0 : afterHide();
450
- }
451
474
  }, [show]);
452
- const handleShowTooltipDelayed = () => {
475
+ const handleShowTooltipDelayed = (delay = delayShow) => {
453
476
  if (tooltipShowDelayTimerRef.current) {
454
477
  clearTimeout(tooltipShowDelayTimerRef.current);
455
478
  }
456
479
  tooltipShowDelayTimerRef.current = setTimeout(() => {
457
480
  handleShow(true);
458
- }, delayShow);
481
+ }, delay);
459
482
  };
460
483
  const handleHideTooltipDelayed = (delay = delayHide) => {
461
484
  if (tooltipHideDelayTimerRef.current) {
@@ -511,6 +534,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
511
534
  }
512
535
  };
513
536
  const handleTooltipPosition = ({ x, y }) => {
537
+ var _a;
514
538
  const virtualElement = {
515
539
  getBoundingClientRect() {
516
540
  return {
@@ -526,7 +550,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
526
550
  },
527
551
  };
528
552
  computeTooltipPosition({
529
- place,
553
+ place: (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.place) !== null && _a !== void 0 ? _a : place,
530
554
  offset,
531
555
  elementReference: virtualElement,
532
556
  tooltipReference: tooltipRef.current,
@@ -558,12 +582,16 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
558
582
  };
559
583
  const handleClickOutsideAnchors = (event) => {
560
584
  var _a;
561
- const anchorById = document.querySelector(`[id='${anchorId}']`);
562
- const anchors = [anchorById, ...anchorsBySelect];
563
- if (anchors.some((anchor) => anchor === null || anchor === void 0 ? void 0 : anchor.contains(event.target))) {
585
+ if (!show) {
586
+ return;
587
+ }
588
+ const target = event.target;
589
+ if ((_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.contains(target)) {
564
590
  return;
565
591
  }
566
- if ((_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) {
592
+ const anchorById = document.querySelector(`[id='${anchorId}']`);
593
+ const anchors = [anchorById, ...anchorsBySelect];
594
+ if (anchors.some((anchor) => anchor === null || anchor === void 0 ? void 0 : anchor.contains(target))) {
567
595
  return;
568
596
  }
569
597
  handleShow(false);
@@ -576,9 +604,11 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
576
604
  const debouncedHandleShowTooltip = debounce(handleShowTooltip, 50, true);
577
605
  const debouncedHandleHideTooltip = debounce(handleHideTooltip, 50, true);
578
606
  const updateTooltipPosition = useCallback(() => {
579
- if (position) {
607
+ var _a, _b;
608
+ const actualPosition = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.position) !== null && _a !== void 0 ? _a : position;
609
+ if (actualPosition) {
580
610
  // if `position` is set, override regular and `float` positioning
581
- handleTooltipPosition(position);
611
+ handleTooltipPosition(actualPosition);
582
612
  return;
583
613
  }
584
614
  if (float) {
@@ -599,7 +629,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
599
629
  return;
600
630
  }
601
631
  computeTooltipPosition({
602
- place,
632
+ place: (_b = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.place) !== null && _b !== void 0 ? _b : place,
603
633
  offset,
604
634
  elementReference: activeAnchor,
605
635
  tooltipReference: tooltipRef.current,
@@ -626,9 +656,11 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
626
656
  content,
627
657
  externalStyles,
628
658
  place,
659
+ imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.place,
629
660
  offset,
630
661
  positionStrategy,
631
662
  position,
663
+ imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.position,
632
664
  float,
633
665
  ]);
634
666
  useEffect(() => {
@@ -785,7 +817,8 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
785
817
  shouldOpenOnClick,
786
818
  ]);
787
819
  useEffect(() => {
788
- let selector = anchorSelect !== null && anchorSelect !== void 0 ? anchorSelect : '';
820
+ var _a, _b;
821
+ let selector = (_b = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect) !== null && _a !== void 0 ? _a : anchorSelect) !== null && _b !== void 0 ? _b : '';
789
822
  if (!selector && id) {
790
823
  selector = `[data-tooltip-id='${id}']`;
791
824
  }
@@ -874,7 +907,7 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
874
907
  return () => {
875
908
  documentObserver.disconnect();
876
909
  };
877
- }, [id, anchorSelect, activeAnchor]);
910
+ }, [id, anchorSelect, imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect, activeAnchor]);
878
911
  useEffect(() => {
879
912
  updateTooltipPosition();
880
913
  }, [updateTooltipPosition]);
@@ -914,7 +947,8 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
914
947
  };
915
948
  }, []);
916
949
  useEffect(() => {
917
- let selector = anchorSelect;
950
+ var _a;
951
+ let selector = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect) !== null && _a !== void 0 ? _a : anchorSelect;
918
952
  if (!selector && id) {
919
953
  selector = `[data-tooltip-id='${id}']`;
920
954
  }
@@ -925,12 +959,47 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
925
959
  const anchors = Array.from(document.querySelectorAll(selector));
926
960
  setAnchorsBySelect(anchors);
927
961
  }
928
- catch (_a) {
962
+ catch (_b) {
929
963
  // warning was already issued in the controller
930
964
  setAnchorsBySelect([]);
931
965
  }
932
- }, [id, anchorSelect]);
933
- const canShow = !hidden && content && show && Object.keys(inlineStyles).length > 0;
966
+ }, [id, anchorSelect, imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.anchorSelect]);
967
+ const actualContent = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.content) !== null && _a !== void 0 ? _a : content;
968
+ const canShow = Boolean(!hidden && actualContent && show && Object.keys(inlineStyles).length > 0);
969
+ useImperativeHandle(forwardRef, () => ({
970
+ open: (options) => {
971
+ if (options === null || options === void 0 ? void 0 : options.anchorSelect) {
972
+ try {
973
+ document.querySelector(options.anchorSelect);
974
+ }
975
+ catch (_a) {
976
+ {
977
+ // eslint-disable-next-line no-console
978
+ console.warn(`[react-tooltip] "${options.anchorSelect}" is not a valid CSS selector`);
979
+ }
980
+ return;
981
+ }
982
+ }
983
+ setImperativeOptions(options !== null && options !== void 0 ? options : null);
984
+ if (options === null || options === void 0 ? void 0 : options.delay) {
985
+ handleShowTooltipDelayed(options.delay);
986
+ }
987
+ else {
988
+ handleShow(true);
989
+ }
990
+ },
991
+ close: (options) => {
992
+ if (options === null || options === void 0 ? void 0 : options.delay) {
993
+ handleHideTooltipDelayed(options.delay);
994
+ }
995
+ else {
996
+ handleShow(false);
997
+ }
998
+ },
999
+ activeAnchor,
1000
+ place: actualPlacement,
1001
+ isOpen: rendered && canShow,
1002
+ }));
934
1003
  return rendered ? (React.createElement(WrapperElement, { id: id, role: "tooltip", className: classNames('react-tooltip', coreStyles['tooltip'], styles['tooltip'], styles[variant], className, `react-tooltip__place-${actualPlacement}`, coreStyles[canShow ? 'show' : 'closing'], canShow ? 'react-tooltip__show' : 'react-tooltip__closing', positionStrategy === 'fixed' && coreStyles['fixed'], clickable && coreStyles['clickable']), onTransitionEnd: (event) => {
935
1004
  /**
936
1005
  * @warning if `--rt-transition-closing-delay` is set to 0,
@@ -940,12 +1009,14 @@ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, bo
940
1009
  return;
941
1010
  }
942
1011
  setRendered(false);
1012
+ setImperativeOptions(null);
1013
+ afterHide === null || afterHide === void 0 ? void 0 : afterHide();
943
1014
  }, style: {
944
1015
  ...externalStyles,
945
1016
  ...inlineStyles,
946
1017
  opacity: opacity !== undefined && canShow ? opacity : undefined,
947
1018
  }, ref: tooltipRef },
948
- content,
1019
+ actualContent,
949
1020
  React.createElement(WrapperElement, { className: classNames('react-tooltip-arrow', coreStyles['arrow'], styles['arrow'], classNameArrow, noArrow && coreStyles['noArrow']), style: {
950
1021
  ...inlineArrowStyles,
951
1022
  background: arrowColor
@@ -959,7 +1030,7 @@ const TooltipContent = ({ content }) => {
959
1030
  return React.createElement("span", { dangerouslySetInnerHTML: { __html: content } });
960
1031
  };
961
1032
 
962
- 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, }) => {
1033
+ 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, openEvents, closeEvents, globalCloseEvents, imperativeModeOnly = false, style, position, isOpen, disableStyleInjection = false, border, opacity, arrowColor, setIsOpen, afterShow, afterHide, }, ref) => {
963
1034
  const [tooltipContent, setTooltipContent] = useState(content);
964
1035
  const [tooltipHtml, setTooltipHtml] = useState(html);
965
1036
  const [tooltipPlace, setTooltipPlace] = useState(place);
@@ -1183,6 +1254,7 @@ const TooltipController = ({ id, anchorId, anchorSelect, content, html, render,
1183
1254
  renderedContent = React.createElement(TooltipContent, { content: tooltipHtml });
1184
1255
  }
1185
1256
  const props = {
1257
+ forwardRef: ref,
1186
1258
  id,
1187
1259
  anchorId,
1188
1260
  anchorSelect,
@@ -1210,6 +1282,7 @@ const TooltipController = ({ id, anchorId, anchorSelect, content, html, render,
1210
1282
  openEvents,
1211
1283
  closeEvents,
1212
1284
  globalCloseEvents,
1285
+ imperativeModeOnly,
1213
1286
  style,
1214
1287
  position,
1215
1288
  isOpen,
@@ -1223,7 +1296,7 @@ const TooltipController = ({ id, anchorId, anchorSelect, content, html, render,
1223
1296
  setActiveAnchor: (anchor) => setActiveAnchor(anchor),
1224
1297
  };
1225
1298
  return React.createElement(Tooltip, { ...props });
1226
- };
1299
+ });
1227
1300
 
1228
1301
  // those content will be replaced in build time with the `react-tooltip.css` builded content
1229
1302
  const TooltipCoreStyles = `:root {