react-tooltip 5.26.1 → 5.26.3

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.
@@ -103,6 +103,96 @@
103
103
  injected[type] = false;
104
104
  }
105
105
 
106
+ const computeTooltipPosition = async ({ elementReference = null, tooltipReference = null, tooltipArrowReference = null, place = 'top', offset: offsetValue = 10, strategy = 'absolute', middlewares = [
107
+ dom.offset(Number(offsetValue)),
108
+ dom.flip({
109
+ fallbackAxisSideDirection: 'start',
110
+ }),
111
+ dom.shift({ padding: 5 }),
112
+ ], border, }) => {
113
+ if (!elementReference) {
114
+ // elementReference can be null or undefined and we will not compute the position
115
+ // eslint-disable-next-line no-console
116
+ // console.error('The reference element for tooltip was not defined: ', elementReference)
117
+ return { tooltipStyles: {}, tooltipArrowStyles: {}, place };
118
+ }
119
+ if (tooltipReference === null) {
120
+ return { tooltipStyles: {}, tooltipArrowStyles: {}, place };
121
+ }
122
+ const middleware = middlewares;
123
+ if (tooltipArrowReference) {
124
+ middleware.push(dom.arrow({ element: tooltipArrowReference, padding: 5 }));
125
+ return dom.computePosition(elementReference, tooltipReference, {
126
+ placement: place,
127
+ strategy,
128
+ middleware,
129
+ }).then(({ x, y, placement, middlewareData }) => {
130
+ var _a, _b;
131
+ const styles = { left: `${x}px`, top: `${y}px`, border };
132
+ /* c8 ignore start */
133
+ const { x: arrowX, y: arrowY } = (_a = middlewareData.arrow) !== null && _a !== void 0 ? _a : { x: 0, y: 0 };
134
+ const staticSide = (_b = {
135
+ top: 'bottom',
136
+ right: 'left',
137
+ bottom: 'top',
138
+ left: 'right',
139
+ }[placement.split('-')[0]]) !== null && _b !== void 0 ? _b : 'bottom';
140
+ /* c8 ignore end */
141
+ const borderSide = border && {
142
+ borderBottom: border,
143
+ borderRight: border,
144
+ };
145
+ let borderWidth = 0;
146
+ if (border) {
147
+ const match = `${border}`.match(/(\d+)px/);
148
+ if (match === null || match === void 0 ? void 0 : match[1]) {
149
+ borderWidth = Number(match[1]);
150
+ }
151
+ else {
152
+ /**
153
+ * this means `border` was set without `width`,
154
+ * or non-px value (such as `medium`, `thick`, ...)
155
+ */
156
+ borderWidth = 1;
157
+ }
158
+ }
159
+ /* c8 ignore start */
160
+ const arrowStyle = {
161
+ left: arrowX != null ? `${arrowX}px` : '',
162
+ top: arrowY != null ? `${arrowY}px` : '',
163
+ right: '',
164
+ bottom: '',
165
+ ...borderSide,
166
+ [staticSide]: `-${4 + borderWidth}px`,
167
+ };
168
+ /* c8 ignore end */
169
+ return { tooltipStyles: styles, tooltipArrowStyles: arrowStyle, place: placement };
170
+ });
171
+ }
172
+ return dom.computePosition(elementReference, tooltipReference, {
173
+ placement: 'bottom',
174
+ strategy,
175
+ middleware,
176
+ }).then(({ x, y, placement }) => {
177
+ const styles = { left: `${x}px`, top: `${y}px` };
178
+ return { tooltipStyles: styles, tooltipArrowStyles: {}, place: placement };
179
+ });
180
+ };
181
+
182
+ const cssSupports = (property, value) => {
183
+ const hasCssSupports = 'CSS' in window && 'supports' in window.CSS;
184
+ return hasCssSupports ? window.CSS.supports(property, value) : true;
185
+ };
186
+
187
+ const cssTimeToMs = (time) => {
188
+ const match = time.match(/^([\d.]+)(ms|s)$/);
189
+ if (!match) {
190
+ return 0;
191
+ }
192
+ const [, amount, unit] = match;
193
+ return Number(amount) * (unit === 'ms' ? 1 : 1000);
194
+ };
195
+
106
196
  /* eslint-disable @typescript-eslint/no-explicit-any */
107
197
  /**
108
198
  * This function debounce the received function
@@ -121,7 +211,7 @@
121
211
  };
122
212
  if (immediate && !timeout) {
123
213
  /**
124
- * there's not need to clear the timeout
214
+ * there's no need to clear the timeout
125
215
  * since we expect it to resolve and set `timeout = null`
126
216
  */
127
217
  func.apply(this, args);
@@ -135,15 +225,70 @@
135
225
  }
136
226
  };
137
227
  debounced.cancel = () => {
228
+ /* c8 ignore start */
138
229
  if (!timeout) {
139
230
  return;
140
231
  }
232
+ /* c8 ignore end */
141
233
  clearTimeout(timeout);
142
234
  timeout = null;
143
235
  };
144
236
  return debounced;
145
237
  };
146
238
 
239
+ const isObject = (object) => {
240
+ return object !== null && !Array.isArray(object) && typeof object === 'object';
241
+ };
242
+ const deepEqual = (object1, object2) => {
243
+ if (object1 === object2) {
244
+ return true;
245
+ }
246
+ if (Array.isArray(object1) && Array.isArray(object2)) {
247
+ if (object1.length !== object2.length) {
248
+ return false;
249
+ }
250
+ return object1.every((val, index) => deepEqual(val, object2[index]));
251
+ }
252
+ if (Array.isArray(object1) !== Array.isArray(object2)) {
253
+ return false;
254
+ }
255
+ if (!isObject(object1) || !isObject(object2)) {
256
+ return object1 === object2;
257
+ }
258
+ const keys1 = Object.keys(object1);
259
+ const keys2 = Object.keys(object2);
260
+ if (keys1.length !== keys2.length) {
261
+ return false;
262
+ }
263
+ return keys1.every((key) => deepEqual(object1[key], object2[key]));
264
+ };
265
+
266
+ const isScrollable = (node) => {
267
+ if (!(node instanceof HTMLElement || node instanceof SVGElement)) {
268
+ return false;
269
+ }
270
+ const style = getComputedStyle(node);
271
+ return ['overflow', 'overflow-x', 'overflow-y'].some((propertyName) => {
272
+ const value = style.getPropertyValue(propertyName);
273
+ return value === 'auto' || value === 'scroll';
274
+ });
275
+ };
276
+ const getScrollParent = (node) => {
277
+ if (!node) {
278
+ return null;
279
+ }
280
+ let currentParent = node.parentElement;
281
+ while (currentParent) {
282
+ if (isScrollable(currentParent)) {
283
+ return currentParent;
284
+ }
285
+ currentParent = currentParent.parentElement;
286
+ }
287
+ return document.scrollingElement || document.documentElement;
288
+ };
289
+
290
+ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
291
+
147
292
  const DEFAULT_TOOLTIP_ID = 'DEFAULT_TOOLTIP_ID';
148
293
  const DEFAULT_CONTEXT_DATA = {
149
294
  anchorRefs: new Set(),
@@ -242,115 +387,6 @@
242
387
  return (React__default["default"].createElement("span", { ref: anchorRef, className: classNames__default["default"]('react-tooltip-wrapper', className), "data-tooltip-place": place, "data-tooltip-content": content, "data-tooltip-html": html, "data-tooltip-variant": variant, "data-tooltip-offset": offset, "data-tooltip-wrapper": wrapper, "data-tooltip-events": events, "data-tooltip-position-strategy": positionStrategy, "data-tooltip-delay-show": delayShow, "data-tooltip-delay-hide": delayHide }, children));
243
388
  };
244
389
 
245
- const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
246
-
247
- const isScrollable = (node) => {
248
- if (!(node instanceof HTMLElement || node instanceof SVGElement)) {
249
- return false;
250
- }
251
- const style = getComputedStyle(node);
252
- return ['overflow', 'overflow-x', 'overflow-y'].some((propertyName) => {
253
- const value = style.getPropertyValue(propertyName);
254
- return value === 'auto' || value === 'scroll';
255
- });
256
- };
257
- const getScrollParent = (node) => {
258
- if (!node) {
259
- return null;
260
- }
261
- let currentParent = node.parentElement;
262
- while (currentParent) {
263
- if (isScrollable(currentParent)) {
264
- return currentParent;
265
- }
266
- currentParent = currentParent.parentElement;
267
- }
268
- return document.scrollingElement || document.documentElement;
269
- };
270
-
271
- const computeTooltipPosition = async ({ elementReference = null, tooltipReference = null, tooltipArrowReference = null, place = 'top', offset: offsetValue = 10, strategy = 'absolute', middlewares = [
272
- dom.offset(Number(offsetValue)),
273
- dom.flip({
274
- fallbackAxisSideDirection: 'start',
275
- }),
276
- dom.shift({ padding: 5 }),
277
- ], border, }) => {
278
- if (!elementReference) {
279
- // elementReference can be null or undefined and we will not compute the position
280
- // eslint-disable-next-line no-console
281
- // console.error('The reference element for tooltip was not defined: ', elementReference)
282
- return { tooltipStyles: {}, tooltipArrowStyles: {}, place };
283
- }
284
- if (tooltipReference === null) {
285
- return { tooltipStyles: {}, tooltipArrowStyles: {}, place };
286
- }
287
- const middleware = middlewares;
288
- if (tooltipArrowReference) {
289
- middleware.push(dom.arrow({ element: tooltipArrowReference, padding: 5 }));
290
- return dom.computePosition(elementReference, tooltipReference, {
291
- placement: place,
292
- strategy,
293
- middleware,
294
- }).then(({ x, y, placement, middlewareData }) => {
295
- var _a, _b;
296
- const styles = { left: `${x}px`, top: `${y}px`, border };
297
- const { x: arrowX, y: arrowY } = (_a = middlewareData.arrow) !== null && _a !== void 0 ? _a : { x: 0, y: 0 };
298
- const staticSide = (_b = {
299
- top: 'bottom',
300
- right: 'left',
301
- bottom: 'top',
302
- left: 'right',
303
- }[placement.split('-')[0]]) !== null && _b !== void 0 ? _b : 'bottom';
304
- const borderSide = border && {
305
- borderBottom: border,
306
- borderRight: border,
307
- };
308
- let borderWidth = 0;
309
- if (border) {
310
- const match = `${border}`.match(/(\d+)px/);
311
- if (match === null || match === void 0 ? void 0 : match[1]) {
312
- borderWidth = Number(match[1]);
313
- }
314
- else {
315
- /**
316
- * this means `border` was set without `width`, or non-px value
317
- */
318
- borderWidth = 1;
319
- }
320
- }
321
- const arrowStyle = {
322
- left: arrowX != null ? `${arrowX}px` : '',
323
- top: arrowY != null ? `${arrowY}px` : '',
324
- right: '',
325
- bottom: '',
326
- ...borderSide,
327
- [staticSide]: `-${4 + borderWidth}px`,
328
- };
329
- return { tooltipStyles: styles, tooltipArrowStyles: arrowStyle, place: placement };
330
- });
331
- }
332
- return dom.computePosition(elementReference, tooltipReference, {
333
- placement: 'bottom',
334
- strategy,
335
- middleware,
336
- }).then(({ x, y, placement }) => {
337
- const styles = { left: `${x}px`, top: `${y}px` };
338
- return { tooltipStyles: styles, tooltipArrowStyles: {}, place: placement };
339
- });
340
- };
341
-
342
- const cssTimeToMs = (time) => {
343
- const match = time.match(/^([\d.]+)(m?s?)$/);
344
- if (!match) {
345
- return 0;
346
- }
347
- const [, amount, unit] = match;
348
- if (unit !== 's' && unit !== 'ms') {
349
- return 0;
350
- }
351
- return Number(amount) * (unit === 'ms' ? 1 : 1000);
352
- };
353
-
354
390
  var coreStyles = {"tooltip":"core-styles-module_tooltip__3vRRp","fixed":"core-styles-module_fixed__pcSol","arrow":"core-styles-module_arrow__cvMwQ","noArrow":"core-styles-module_noArrow__xock6","clickable":"core-styles-module_clickable__ZuTTB","show":"core-styles-module_show__Nt9eE","closing":"core-styles-module_closing__sGnxF"};
355
391
 
356
392
  var styles = {"tooltip":"styles-module_tooltip__mnnfp","arrow":"styles-module_arrow__K0L3T","dark":"styles-module_dark__xNqje","light":"styles-module_light__Z6W-X","success":"styles-module_success__A2AKt","warning":"styles-module_warning__SCK0X","error":"styles-module_error__JvumD","info":"styles-module_info__BWdHW"};
@@ -366,9 +402,11 @@
366
402
  const tooltipShowDelayTimerRef = React.useRef(null);
367
403
  const tooltipHideDelayTimerRef = React.useRef(null);
368
404
  const missedTransitionTimerRef = React.useRef(null);
369
- const [actualPlacement, setActualPlacement] = React.useState(place);
370
- const [inlineStyles, setInlineStyles] = React.useState({});
371
- const [inlineArrowStyles, setInlineArrowStyles] = React.useState({});
405
+ const [computedPosition, setComputedPosition] = React.useState({
406
+ tooltipStyles: {},
407
+ tooltipArrowStyles: {},
408
+ place,
409
+ });
372
410
  const [show, setShow] = React.useState(false);
373
411
  const [rendered, setRendered] = React.useState(false);
374
412
  const [imperativeOptions, setImperativeOptions] = React.useState(null);
@@ -526,6 +564,11 @@
526
564
  }, transitionShowDelay + 25);
527
565
  }
528
566
  }, [show]);
567
+ const handleComputedPosition = (newComputedPosition) => {
568
+ setComputedPosition((oldComputedPosition) => deepEqual(oldComputedPosition, newComputedPosition)
569
+ ? oldComputedPosition
570
+ : newComputedPosition);
571
+ };
529
572
  const handleShowTooltipDelayed = (delay = delayShow) => {
530
573
  if (tooltipShowDelayTimerRef.current) {
531
574
  clearTimeout(tooltipShowDelayTimerRef.current);
@@ -618,13 +661,7 @@
618
661
  middlewares,
619
662
  border,
620
663
  }).then((computedStylesData) => {
621
- if (Object.keys(computedStylesData.tooltipStyles).length) {
622
- setInlineStyles(computedStylesData.tooltipStyles);
623
- }
624
- if (Object.keys(computedStylesData.tooltipArrowStyles).length) {
625
- setInlineArrowStyles(computedStylesData.tooltipArrowStyles);
626
- }
627
- setActualPlacement(computedStylesData.place);
664
+ handleComputedPosition(computedStylesData);
628
665
  });
629
666
  };
630
667
  const handlePointerMove = (event) => {
@@ -717,13 +754,7 @@
717
754
  // invalidate computed positions after remount
718
755
  return;
719
756
  }
720
- if (Object.keys(computedStylesData.tooltipStyles).length) {
721
- setInlineStyles(computedStylesData.tooltipStyles);
722
- }
723
- if (Object.keys(computedStylesData.tooltipArrowStyles).length) {
724
- setInlineArrowStyles(computedStylesData.tooltipArrowStyles);
725
- }
726
- setActualPlacement(computedStylesData.place);
757
+ handleComputedPosition(computedStylesData);
727
758
  });
728
759
  }, [
729
760
  show,
@@ -1066,7 +1097,7 @@
1066
1097
  }
1067
1098
  }, [delayShow]);
1068
1099
  const actualContent = (_a = imperativeOptions === null || imperativeOptions === void 0 ? void 0 : imperativeOptions.content) !== null && _a !== void 0 ? _a : content;
1069
- const canShow = show && Object.keys(inlineStyles).length > 0;
1100
+ const canShow = show && Object.keys(computedPosition.tooltipStyles).length > 0;
1070
1101
  React.useImperativeHandle(forwardRef, () => ({
1071
1102
  open: (options) => {
1072
1103
  if (options === null || options === void 0 ? void 0 : options.anchorSelect) {
@@ -1098,10 +1129,10 @@
1098
1129
  }
1099
1130
  },
1100
1131
  activeAnchor,
1101
- place: actualPlacement,
1132
+ place: computedPosition.place,
1102
1133
  isOpen: Boolean(rendered && !hidden && actualContent && canShow),
1103
1134
  }));
1104
- return rendered && !hidden && actualContent ? (React__default["default"].createElement(WrapperElement, { id: id, role: role, className: classNames__default["default"]('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) => {
1135
+ return rendered && !hidden && actualContent ? (React__default["default"].createElement(WrapperElement, { id: id, role: role, className: classNames__default["default"]('react-tooltip', coreStyles['tooltip'], styles['tooltip'], styles[variant], className, `react-tooltip__place-${computedPosition.place}`, coreStyles[canShow ? 'show' : 'closing'], canShow ? 'react-tooltip__show' : 'react-tooltip__closing', positionStrategy === 'fixed' && coreStyles['fixed'], clickable && coreStyles['clickable']), onTransitionEnd: (event) => {
1105
1136
  if (missedTransitionTimerRef.current) {
1106
1137
  clearTimeout(missedTransitionTimerRef.current);
1107
1138
  }
@@ -1113,12 +1144,12 @@
1113
1144
  afterHide === null || afterHide === void 0 ? void 0 : afterHide();
1114
1145
  }, style: {
1115
1146
  ...externalStyles,
1116
- ...inlineStyles,
1147
+ ...computedPosition.tooltipStyles,
1117
1148
  opacity: opacity !== undefined && canShow ? opacity : undefined,
1118
1149
  }, ref: tooltipRef },
1119
1150
  actualContent,
1120
1151
  React__default["default"].createElement(WrapperElement, { className: classNames__default["default"]('react-tooltip-arrow', coreStyles['arrow'], styles['arrow'], classNameArrow, noArrow && coreStyles['noArrow']), style: {
1121
- ...inlineArrowStyles,
1152
+ ...computedPosition.tooltipArrowStyles,
1122
1153
  background: arrowColor
1123
1154
  ? `linear-gradient(to right bottom, transparent 50%, ${arrowColor} 50%)`
1124
1155
  : undefined,
@@ -1130,11 +1161,6 @@
1130
1161
  return React__default["default"].createElement("span", { dangerouslySetInnerHTML: { __html: content } });
1131
1162
  };
1132
1163
 
1133
- const cssSupports = (property, value) => {
1134
- const hasCssSupports = 'CSS' in window && 'supports' in window.CSS;
1135
- return hasCssSupports ? window.CSS.supports(property, value) : true;
1136
- };
1137
-
1138
1164
  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, openEvents, closeEvents, globalCloseEvents, imperativeModeOnly = false, style, position, isOpen, defaultIsOpen = false, disableStyleInjection = false, border, opacity, arrowColor, setIsOpen, afterShow, afterHide, role = 'tooltip', }, ref) => {
1139
1165
  const [tooltipContent, setTooltipContent] = React.useState(content);
1140
1166
  const [tooltipHtml, setTooltipHtml] = React.useState(html);
@@ -1255,10 +1281,12 @@
1255
1281
  if (styleInjectionRef.current === disableStyleInjection) {
1256
1282
  return;
1257
1283
  }
1284
+ /* c8 ignore start */
1258
1285
  {
1259
1286
  // eslint-disable-next-line no-console
1260
1287
  console.warn('[react-tooltip] Do not change `disableStyleInjection` dynamically.');
1261
1288
  }
1289
+ /* c8 ignore end */
1262
1290
  }, [disableStyleInjection]);
1263
1291
  React.useEffect(() => {
1264
1292
  if (typeof window !== 'undefined') {
@@ -1285,10 +1313,12 @@
1285
1313
  });
1286
1314
  }
1287
1315
  catch (_b) {
1316
+ /* c8 ignore start */
1288
1317
  {
1289
1318
  // eslint-disable-next-line no-console
1290
1319
  console.warn(`[react-tooltip] "${selector}" is not a valid CSS selector`);
1291
1320
  }
1321
+ /* c8 ignore end */
1292
1322
  }
1293
1323
  }
1294
1324
  const anchorById = document.querySelector(`[id='${anchorId}']`);
@@ -1329,6 +1359,7 @@
1329
1359
  };
1330
1360
  }, [anchorRefs, providerActiveAnchor, activeAnchor, anchorId, anchorSelect]);
1331
1361
  React.useEffect(() => {
1362
+ /* c8 ignore end */
1332
1363
  if (style === null || style === void 0 ? void 0 : style.border) {
1333
1364
  // eslint-disable-next-line no-console
1334
1365
  console.warn('[react-tooltip] Do not set `style.border`. Use `border` prop instead.');