react-tooltip 5.15.0 → 5.16.0-beta.1041.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.
@@ -6,998 +6,1114 @@
6
6
  * @license MIT
7
7
  */
8
8
  (function (global, factory) {
9
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('classnames'), require('@floating-ui/dom')) :
10
- typeof define === 'function' && define.amd ? define(['exports', 'react', 'classnames', '@floating-ui/dom'], factory) :
11
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactTooltip = {}, global.React, global.classNames, global.FloatingUIDOM));
9
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('classnames'), require('@floating-ui/dom')) :
10
+ typeof define === 'function' && define.amd ? define(['exports', 'react', 'classnames', '@floating-ui/dom'], factory) :
11
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactTooltip = {}, global.React, global.classNames, global.FloatingUIDOM));
12
12
  })(this, (function (exports, React, classNames, dom) { 'use strict';
13
13
 
14
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
14
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
15
15
 
16
- var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
17
- var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
16
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
17
+ var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
18
18
 
19
- function styleInject(css, ref) {
20
- if ( ref === void 0 ) ref = {};
21
- var insertAt = ref.insertAt;
22
-
23
- if (!css || typeof document === 'undefined') { return; }
19
+ // This is the ID for the core styles of ReactTooltip
20
+ const REACT_TOOLTIP_CORE_STYLES_ID = 'react-tooltip-core-styles';
21
+ // This is the ID for the visual styles of ReactTooltip
22
+ const REACT_TOOLTIP_BASE_STYLES_ID = 'react-tooltip-base-styles';
23
+ function injectStyle({ css, id = REACT_TOOLTIP_BASE_STYLES_ID, type = 'base', ref, }) {
24
+ if (type === 'core' && process.env.REACT_TOOLTIP_DISABLE_CORE_STYLES) {
25
+ return;
26
+ }
27
+ if (type !== 'core' && process.env.REACT_TOOLTIP_DISABLE_BASE_STYLES) {
28
+ return;
29
+ }
30
+ if (type === 'core') {
31
+ // eslint-disable-next-line no-param-reassign
32
+ id = REACT_TOOLTIP_CORE_STYLES_ID;
33
+ }
34
+ if (!ref) {
35
+ // eslint-disable-next-line no-param-reassign
36
+ ref = {};
37
+ }
38
+ const { insertAt } = ref;
39
+ if (!css || typeof document === 'undefined' || document.getElementById(id)) {
40
+ return;
41
+ }
42
+ const head = document.head || document.getElementsByTagName('head')[0];
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ const style = document.createElement('style');
45
+ style.id = id;
46
+ style.type = 'text/css';
47
+ if (insertAt === 'top') {
48
+ if (head.firstChild) {
49
+ head.insertBefore(style, head.firstChild);
50
+ }
51
+ else {
52
+ head.appendChild(style);
53
+ }
54
+ }
55
+ else {
56
+ head.appendChild(style);
57
+ }
58
+ if (style.styleSheet) {
59
+ style.styleSheet.cssText = css;
60
+ }
61
+ else {
62
+ style.appendChild(document.createTextNode(css));
63
+ }
64
+ }
65
+ function removeStyle({ type = 'base', id = REACT_TOOLTIP_BASE_STYLES_ID, }) {
66
+ if (type === 'core') {
67
+ // eslint-disable-next-line no-param-reassign
68
+ id = REACT_TOOLTIP_CORE_STYLES_ID;
69
+ }
70
+ const style = document.getElementById(id);
71
+ style === null || style === void 0 ? void 0 : style.remove();
72
+ }
24
73
 
25
- var head = document.head || document.getElementsByTagName('head')[0];
26
- var style = document.createElement('style');
27
- style.type = 'text/css';
74
+ /* eslint-disable @typescript-eslint/no-explicit-any */
75
+ /**
76
+ * This function debounce the received function
77
+ * @param { function } func Function to be debounced
78
+ * @param { number } wait Time to wait before execut the function
79
+ * @param { boolean } immediate Param to define if the function will be executed immediately
80
+ */
81
+ const debounce = (func, wait, immediate) => {
82
+ let timeout = null;
83
+ return function debounced(...args) {
84
+ const later = () => {
85
+ timeout = null;
86
+ if (!immediate) {
87
+ func.apply(this, args);
88
+ }
89
+ };
90
+ if (immediate && !timeout) {
91
+ /**
92
+ * there's not need to clear the timeout
93
+ * since we expect it to resolve and set `timeout = null`
94
+ */
95
+ func.apply(this, args);
96
+ timeout = setTimeout(later, wait);
97
+ }
98
+ if (!immediate) {
99
+ if (timeout) {
100
+ clearTimeout(timeout);
101
+ }
102
+ timeout = setTimeout(later, wait);
103
+ }
104
+ };
105
+ };
28
106
 
29
- if (insertAt === 'top') {
30
- if (head.firstChild) {
31
- head.insertBefore(style, head.firstChild);
32
- } else {
33
- head.appendChild(style);
34
- }
35
- } else {
36
- head.appendChild(style);
107
+ const DEFAULT_TOOLTIP_ID = 'DEFAULT_TOOLTIP_ID';
108
+ const DEFAULT_CONTEXT_DATA = {
109
+ anchorRefs: new Set(),
110
+ activeAnchor: { current: null },
111
+ attach: () => {
112
+ /* attach anchor element */
113
+ },
114
+ detach: () => {
115
+ /* detach anchor element */
116
+ },
117
+ setActiveAnchor: () => {
118
+ /* set active anchor */
119
+ },
120
+ };
121
+ const DEFAULT_CONTEXT_DATA_WRAPPER = {
122
+ getTooltipData: () => DEFAULT_CONTEXT_DATA,
123
+ };
124
+ const TooltipContext = React.createContext(DEFAULT_CONTEXT_DATA_WRAPPER);
125
+ /**
126
+ * @deprecated Use the `data-tooltip-id` attribute, or the `anchorSelect` prop instead.
127
+ * See https://react-tooltip.com/docs/getting-started
128
+ */
129
+ const TooltipProvider = ({ children }) => {
130
+ const [anchorRefMap, setAnchorRefMap] = React.useState({
131
+ [DEFAULT_TOOLTIP_ID]: new Set(),
132
+ });
133
+ const [activeAnchorMap, setActiveAnchorMap] = React.useState({
134
+ [DEFAULT_TOOLTIP_ID]: { current: null },
135
+ });
136
+ const attach = (tooltipId, ...refs) => {
137
+ setAnchorRefMap((oldMap) => {
138
+ var _a;
139
+ const tooltipRefs = (_a = oldMap[tooltipId]) !== null && _a !== void 0 ? _a : new Set();
140
+ refs.forEach((ref) => tooltipRefs.add(ref));
141
+ // create new object to trigger re-render
142
+ return { ...oldMap, [tooltipId]: new Set(tooltipRefs) };
143
+ });
144
+ };
145
+ const detach = (tooltipId, ...refs) => {
146
+ setAnchorRefMap((oldMap) => {
147
+ const tooltipRefs = oldMap[tooltipId];
148
+ if (!tooltipRefs) {
149
+ // tooltip not found
150
+ // maybe thow error?
151
+ return oldMap;
152
+ }
153
+ refs.forEach((ref) => tooltipRefs.delete(ref));
154
+ // create new object to trigger re-render
155
+ return { ...oldMap };
156
+ });
157
+ };
158
+ const setActiveAnchor = (tooltipId, ref) => {
159
+ setActiveAnchorMap((oldMap) => {
160
+ var _a;
161
+ if (((_a = oldMap[tooltipId]) === null || _a === void 0 ? void 0 : _a.current) === ref.current) {
162
+ return oldMap;
163
+ }
164
+ // create new object to trigger re-render
165
+ return { ...oldMap, [tooltipId]: ref };
166
+ });
167
+ };
168
+ const getTooltipData = React.useCallback((tooltipId = DEFAULT_TOOLTIP_ID) => {
169
+ var _a, _b;
170
+ return ({
171
+ anchorRefs: (_a = anchorRefMap[tooltipId]) !== null && _a !== void 0 ? _a : new Set(),
172
+ activeAnchor: (_b = activeAnchorMap[tooltipId]) !== null && _b !== void 0 ? _b : { current: null },
173
+ attach: (...refs) => attach(tooltipId, ...refs),
174
+ detach: (...refs) => detach(tooltipId, ...refs),
175
+ setActiveAnchor: (ref) => setActiveAnchor(tooltipId, ref),
176
+ });
177
+ }, [anchorRefMap, activeAnchorMap, attach, detach]);
178
+ const context = React.useMemo(() => {
179
+ return {
180
+ getTooltipData,
181
+ };
182
+ }, [getTooltipData]);
183
+ return React__default["default"].createElement(TooltipContext.Provider, { value: context }, children);
184
+ };
185
+ function useTooltip(tooltipId = DEFAULT_TOOLTIP_ID) {
186
+ return React.useContext(TooltipContext).getTooltipData(tooltipId);
37
187
  }
38
188
 
39
- if (style.styleSheet) {
40
- style.styleSheet.cssText = css;
41
- } else {
42
- style.appendChild(document.createTextNode(css));
43
- }
44
- }
45
-
46
- var css_248z$1 = ":root {\n --rt-color-white: #fff;\n --rt-color-dark: #222;\n --rt-color-success: #8dc572;\n --rt-color-error: #be6464;\n --rt-color-warning: #f0ad4e;\n --rt-color-info: #337ab7;\n --rt-opacity: 0.9;\n}\n";
47
- styleInject(css_248z$1);
48
-
49
- /* eslint-disable @typescript-eslint/no-explicit-any */
50
- /**
51
- * This function debounce the received function
52
- * @param { function } func Function to be debounced
53
- * @param { number } wait Time to wait before execut the function
54
- * @param { boolean } immediate Param to define if the function will be executed immediately
55
- */
56
- const debounce = (func, wait, immediate) => {
57
- let timeout = null;
58
- return function debounced(...args) {
59
- const later = () => {
60
- timeout = null;
61
- if (!immediate) {
62
- func.apply(this, args);
63
- }
64
- };
65
- if (immediate && !timeout) {
66
- /**
67
- * there's not need to clear the timeout
68
- * since we expect it to resolve and set `timeout = null`
69
- */
70
- func.apply(this, args);
71
- timeout = setTimeout(later, wait);
72
- }
73
- if (!immediate) {
74
- if (timeout) {
75
- clearTimeout(timeout);
76
- }
77
- timeout = setTimeout(later, wait);
78
- }
79
- };
80
- };
81
-
82
- const DEFAULT_TOOLTIP_ID = 'DEFAULT_TOOLTIP_ID';
83
- const DEFAULT_CONTEXT_DATA = {
84
- anchorRefs: new Set(),
85
- activeAnchor: { current: null },
86
- attach: () => {
87
- /* attach anchor element */
88
- },
89
- detach: () => {
90
- /* detach anchor element */
91
- },
92
- setActiveAnchor: () => {
93
- /* set active anchor */
94
- },
95
- };
96
- const DEFAULT_CONTEXT_DATA_WRAPPER = {
97
- getTooltipData: () => DEFAULT_CONTEXT_DATA,
98
- };
99
- const TooltipContext = React.createContext(DEFAULT_CONTEXT_DATA_WRAPPER);
100
- /**
101
- * @deprecated Use the `data-tooltip-id` attribute, or the `anchorSelect` prop instead.
102
- * See https://react-tooltip.com/docs/getting-started
103
- */
104
- const TooltipProvider = ({ children }) => {
105
- const [anchorRefMap, setAnchorRefMap] = React.useState({
106
- [DEFAULT_TOOLTIP_ID]: new Set(),
107
- });
108
- const [activeAnchorMap, setActiveAnchorMap] = React.useState({
109
- [DEFAULT_TOOLTIP_ID]: { current: null },
110
- });
111
- const attach = (tooltipId, ...refs) => {
112
- setAnchorRefMap((oldMap) => {
113
- var _a;
114
- const tooltipRefs = (_a = oldMap[tooltipId]) !== null && _a !== void 0 ? _a : new Set();
115
- refs.forEach((ref) => tooltipRefs.add(ref));
116
- // create new object to trigger re-render
117
- return { ...oldMap, [tooltipId]: new Set(tooltipRefs) };
118
- });
119
- };
120
- const detach = (tooltipId, ...refs) => {
121
- setAnchorRefMap((oldMap) => {
122
- const tooltipRefs = oldMap[tooltipId];
123
- if (!tooltipRefs) {
124
- // tooltip not found
125
- // maybe thow error?
126
- return oldMap;
127
- }
128
- refs.forEach((ref) => tooltipRefs.delete(ref));
129
- // create new object to trigger re-render
130
- return { ...oldMap };
131
- });
132
- };
133
- const setActiveAnchor = (tooltipId, ref) => {
134
- setActiveAnchorMap((oldMap) => {
135
- var _a;
136
- if (((_a = oldMap[tooltipId]) === null || _a === void 0 ? void 0 : _a.current) === ref.current) {
137
- return oldMap;
138
- }
139
- // create new object to trigger re-render
140
- return { ...oldMap, [tooltipId]: ref };
141
- });
142
- };
143
- const getTooltipData = React.useCallback((tooltipId = DEFAULT_TOOLTIP_ID) => {
144
- var _a, _b;
145
- return ({
146
- anchorRefs: (_a = anchorRefMap[tooltipId]) !== null && _a !== void 0 ? _a : new Set(),
147
- activeAnchor: (_b = activeAnchorMap[tooltipId]) !== null && _b !== void 0 ? _b : { current: null },
148
- attach: (...refs) => attach(tooltipId, ...refs),
149
- detach: (...refs) => detach(tooltipId, ...refs),
150
- setActiveAnchor: (ref) => setActiveAnchor(tooltipId, ref),
151
- });
152
- }, [anchorRefMap, activeAnchorMap, attach, detach]);
153
- const context = React.useMemo(() => {
154
- return {
155
- getTooltipData,
156
- };
157
- }, [getTooltipData]);
158
- return React__default["default"].createElement(TooltipContext.Provider, { value: context }, children);
159
- };
160
- function useTooltip(tooltipId = DEFAULT_TOOLTIP_ID) {
161
- return React.useContext(TooltipContext).getTooltipData(tooltipId);
162
- }
163
-
164
- /**
165
- * @deprecated Use the `data-tooltip-id` attribute, or the `anchorSelect` prop instead.
166
- * See https://react-tooltip.com/docs/getting-started
167
- */
168
- const TooltipWrapper = ({ tooltipId, children, className, place, content, html, variant, offset, wrapper, events, positionStrategy, delayShow, delayHide, }) => {
169
- const { attach, detach } = useTooltip(tooltipId);
170
- const anchorRef = React.useRef(null);
171
- React.useEffect(() => {
172
- attach(anchorRef);
173
- return () => {
174
- detach(anchorRef);
175
- };
176
- }, []);
177
- 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));
178
- };
179
-
180
- const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
181
-
182
- const isScrollable = (node) => {
183
- if (!(node instanceof HTMLElement || node instanceof SVGElement)) {
184
- return false;
185
- }
186
- const style = getComputedStyle(node);
187
- return ['overflow', 'overflow-x', 'overflow-y'].some((propertyName) => {
188
- const value = style.getPropertyValue(propertyName);
189
- return value === 'auto' || value === 'scroll';
190
- });
191
- };
192
- const getScrollParent = (node) => {
193
- if (!node) {
194
- return null;
195
- }
196
- let currentParent = node.parentElement;
197
- while (currentParent) {
198
- if (isScrollable(currentParent)) {
199
- return currentParent;
200
- }
201
- currentParent = currentParent.parentElement;
202
- }
203
- return document.scrollingElement || document.documentElement;
204
- };
205
-
206
- const computeTooltipPosition = async ({ elementReference = null, tooltipReference = null, tooltipArrowReference = null, place = 'top', offset: offsetValue = 10, strategy = 'absolute', middlewares = [dom.offset(Number(offsetValue)), dom.flip(), dom.shift({ padding: 5 })], }) => {
207
- if (!elementReference) {
208
- // elementReference can be null or undefined and we will not compute the position
209
- // eslint-disable-next-line no-console
210
- // console.error('The reference element for tooltip was not defined: ', elementReference)
211
- return { tooltipStyles: {}, tooltipArrowStyles: {}, place };
212
- }
213
- if (tooltipReference === null) {
214
- return { tooltipStyles: {}, tooltipArrowStyles: {}, place };
215
- }
216
- const middleware = middlewares;
217
- if (tooltipArrowReference) {
218
- middleware.push(dom.arrow({ element: tooltipArrowReference, padding: 5 }));
219
- return dom.computePosition(elementReference, tooltipReference, {
220
- placement: place,
221
- strategy,
222
- middleware,
223
- }).then(({ x, y, placement, middlewareData }) => {
224
- var _a, _b;
225
- const styles = { left: `${x}px`, top: `${y}px` };
226
- const { x: arrowX, y: arrowY } = (_a = middlewareData.arrow) !== null && _a !== void 0 ? _a : { x: 0, y: 0 };
227
- const staticSide = (_b = {
228
- top: 'bottom',
229
- right: 'left',
230
- bottom: 'top',
231
- left: 'right',
232
- }[placement.split('-')[0]]) !== null && _b !== void 0 ? _b : 'bottom';
233
- const arrowStyle = {
234
- left: arrowX != null ? `${arrowX}px` : '',
235
- top: arrowY != null ? `${arrowY}px` : '',
236
- right: '',
237
- bottom: '',
238
- [staticSide]: '-4px',
239
- };
240
- return { tooltipStyles: styles, tooltipArrowStyles: arrowStyle, place: placement };
241
- });
242
- }
243
- return dom.computePosition(elementReference, tooltipReference, {
244
- placement: 'bottom',
245
- strategy,
246
- middleware,
247
- }).then(({ x, y, placement }) => {
248
- const styles = { left: `${x}px`, top: `${y}px` };
249
- return { tooltipStyles: styles, tooltipArrowStyles: {}, place: placement };
250
- });
251
- };
252
-
253
- var css_248z = ".styles-module_tooltip__mnnfp {\n visibility: hidden;\n width: max-content;\n position: absolute;\n top: 0;\n left: 0;\n padding: 8px 16px;\n border-radius: 3px;\n font-size: 90%;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.3s ease-out;\n will-change: opacity, visibility;\n}\n\n.styles-module_fixed__7ciUi {\n position: fixed;\n}\n\n.styles-module_arrow__K0L3T {\n position: absolute;\n background: inherit;\n width: 8px;\n height: 8px;\n transform: rotate(45deg);\n}\n\n.styles-module_noArrow__T8y2L {\n display: none;\n}\n\n.styles-module_clickable__Bv9o7 {\n pointer-events: auto;\n}\n\n.styles-module_show__2NboJ {\n visibility: visible;\n opacity: var(--rt-opacity);\n}\n\n/** Types variant **/\n.styles-module_dark__xNqje {\n background: var(--rt-color-dark);\n color: var(--rt-color-white);\n}\n\n.styles-module_light__Z6W-X {\n background-color: var(--rt-color-white);\n color: var(--rt-color-dark);\n}\n\n.styles-module_success__A2AKt {\n background-color: var(--rt-color-success);\n color: var(--rt-color-white);\n}\n\n.styles-module_warning__SCK0X {\n background-color: var(--rt-color-warning);\n color: var(--rt-color-white);\n}\n\n.styles-module_error__JvumD {\n background-color: var(--rt-color-error);\n color: var(--rt-color-white);\n}\n\n.styles-module_info__BWdHW {\n background-color: var(--rt-color-info);\n color: var(--rt-color-white);\n}\n";
254
- var styles = {"tooltip":"styles-module_tooltip__mnnfp","fixed":"styles-module_fixed__7ciUi","arrow":"styles-module_arrow__K0L3T","noArrow":"styles-module_noArrow__T8y2L","clickable":"styles-module_clickable__Bv9o7","show":"styles-module_show__2NboJ","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"};
255
- styleInject(css_248z);
256
-
257
- const Tooltip = ({
258
- // props
259
- 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,
260
- // props handled by controller
261
- content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, }) => {
262
- const tooltipRef = React.useRef(null);
263
- const tooltipArrowRef = React.useRef(null);
264
- const tooltipShowDelayTimerRef = React.useRef(null);
265
- const tooltipHideDelayTimerRef = React.useRef(null);
266
- const [actualPlacement, setActualPlacement] = React.useState(place);
267
- const [inlineStyles, setInlineStyles] = React.useState({});
268
- const [inlineArrowStyles, setInlineArrowStyles] = React.useState({});
269
- const [show, setShow] = React.useState(false);
270
- const [rendered, setRendered] = React.useState(false);
271
- const wasShowing = React.useRef(false);
272
- const lastFloatPosition = React.useRef(null);
273
- /**
274
- * @todo Remove this in a future version (provider/wrapper method is deprecated)
275
- */
276
- const { anchorRefs, setActiveAnchor: setProviderActiveAnchor } = useTooltip(id);
277
- const hoveringTooltip = React.useRef(false);
278
- const [anchorsBySelect, setAnchorsBySelect] = React.useState([]);
279
- const mounted = React.useRef(false);
280
- const shouldOpenOnClick = openOnClick || events.includes('click');
281
- /**
282
- * useLayoutEffect runs before useEffect,
283
- * but should be used carefully because of caveats
284
- * https://beta.reactjs.org/reference/react/useLayoutEffect#caveats
285
- */
286
- useIsomorphicLayoutEffect(() => {
287
- mounted.current = true;
288
- return () => {
289
- mounted.current = false;
290
- };
291
- }, []);
292
- React.useEffect(() => {
293
- if (!show) {
294
- /**
295
- * this fixes weird behavior when switching between two anchor elements very quickly
296
- * remove the timeout and switch quickly between two adjancent anchor elements to see it
297
- *
298
- * in practice, this means the tooltip is not immediately removed from the DOM on hide
299
- */
300
- const timeout = setTimeout(() => {
301
- setRendered(false);
302
- }, 150);
303
- return () => {
304
- clearTimeout(timeout);
305
- };
306
- }
307
- return () => null;
308
- }, [show]);
309
- const handleShow = (value) => {
310
- if (!mounted.current) {
311
- return;
312
- }
313
- if (value) {
314
- setRendered(true);
315
- }
316
- /**
317
- * wait for the component to render and calculate position
318
- * before actually showing
319
- */
320
- setTimeout(() => {
321
- if (!mounted.current) {
322
- return;
323
- }
324
- setIsOpen === null || setIsOpen === void 0 ? void 0 : setIsOpen(value);
325
- if (isOpen === undefined) {
326
- setShow(value);
327
- }
328
- }, 10);
329
- };
330
- /**
331
- * this replicates the effect from `handleShow()`
332
- * when `isOpen` is changed from outside
333
- */
334
- React.useEffect(() => {
335
- if (isOpen === undefined) {
336
- return () => null;
337
- }
338
- if (isOpen) {
339
- setRendered(true);
340
- }
341
- const timeout = setTimeout(() => {
342
- setShow(isOpen);
343
- }, 10);
344
- return () => {
345
- clearTimeout(timeout);
346
- };
347
- }, [isOpen]);
348
- React.useEffect(() => {
349
- if (show === wasShowing.current) {
350
- return;
351
- }
352
- wasShowing.current = show;
353
- if (show) {
354
- afterShow === null || afterShow === void 0 ? void 0 : afterShow();
355
- }
356
- else {
357
- afterHide === null || afterHide === void 0 ? void 0 : afterHide();
358
- }
359
- }, [show]);
360
- const handleShowTooltipDelayed = () => {
361
- if (tooltipShowDelayTimerRef.current) {
362
- clearTimeout(tooltipShowDelayTimerRef.current);
363
- }
364
- tooltipShowDelayTimerRef.current = setTimeout(() => {
365
- handleShow(true);
366
- }, delayShow);
367
- };
368
- const handleHideTooltipDelayed = (delay = delayHide) => {
369
- if (tooltipHideDelayTimerRef.current) {
370
- clearTimeout(tooltipHideDelayTimerRef.current);
371
- }
372
- tooltipHideDelayTimerRef.current = setTimeout(() => {
373
- if (hoveringTooltip.current) {
374
- return;
375
- }
376
- handleShow(false);
377
- }, delay);
378
- };
379
- const handleShowTooltip = (event) => {
380
- var _a;
381
- if (!event) {
382
- return;
383
- }
384
- const target = ((_a = event.currentTarget) !== null && _a !== void 0 ? _a : event.target);
385
- if (!(target === null || target === void 0 ? void 0 : target.isConnected)) {
386
- /**
387
- * this happens when the target is removed from the DOM
388
- * at the same time the tooltip gets triggered
389
- */
390
- setActiveAnchor(null);
391
- setProviderActiveAnchor({ current: null });
392
- return;
393
- }
394
- if (delayShow) {
395
- handleShowTooltipDelayed();
396
- }
397
- else {
398
- handleShow(true);
399
- }
400
- setActiveAnchor(target);
401
- setProviderActiveAnchor({ current: target });
402
- if (tooltipHideDelayTimerRef.current) {
403
- clearTimeout(tooltipHideDelayTimerRef.current);
404
- }
405
- };
406
- const handleHideTooltip = () => {
407
- if (clickable) {
408
- // allow time for the mouse to reach the tooltip, in case there's a gap
409
- handleHideTooltipDelayed(delayHide || 100);
410
- }
411
- else if (delayHide) {
412
- handleHideTooltipDelayed();
413
- }
414
- else {
415
- handleShow(false);
416
- }
417
- if (tooltipShowDelayTimerRef.current) {
418
- clearTimeout(tooltipShowDelayTimerRef.current);
419
- }
420
- };
421
- const handleTooltipPosition = ({ x, y }) => {
422
- const virtualElement = {
423
- getBoundingClientRect() {
424
- return {
425
- x,
426
- y,
427
- width: 0,
428
- height: 0,
429
- top: y,
430
- left: x,
431
- right: x,
432
- bottom: y,
433
- };
434
- },
435
- };
436
- computeTooltipPosition({
437
- place,
438
- offset,
439
- elementReference: virtualElement,
440
- tooltipReference: tooltipRef.current,
441
- tooltipArrowReference: tooltipArrowRef.current,
442
- strategy: positionStrategy,
443
- middlewares,
444
- }).then((computedStylesData) => {
445
- if (Object.keys(computedStylesData.tooltipStyles).length) {
446
- setInlineStyles(computedStylesData.tooltipStyles);
447
- }
448
- if (Object.keys(computedStylesData.tooltipArrowStyles).length) {
449
- setInlineArrowStyles(computedStylesData.tooltipArrowStyles);
450
- }
451
- setActualPlacement(computedStylesData.place);
452
- });
453
- };
454
- const handleMouseMove = (event) => {
455
- if (!event) {
456
- return;
457
- }
458
- const mouseEvent = event;
459
- const mousePosition = {
460
- x: mouseEvent.clientX,
461
- y: mouseEvent.clientY,
462
- };
463
- handleTooltipPosition(mousePosition);
464
- lastFloatPosition.current = mousePosition;
465
- };
466
- const handleClickTooltipAnchor = (event) => {
467
- handleShowTooltip(event);
468
- if (delayHide) {
469
- handleHideTooltipDelayed();
470
- }
471
- };
472
- const handleClickOutsideAnchors = (event) => {
473
- var _a;
474
- const anchorById = document.querySelector(`[id='${anchorId}']`);
475
- const anchors = [anchorById, ...anchorsBySelect];
476
- if (anchors.some((anchor) => anchor === null || anchor === void 0 ? void 0 : anchor.contains(event.target))) {
477
- return;
478
- }
479
- if ((_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) {
480
- return;
481
- }
482
- handleShow(false);
483
- if (tooltipShowDelayTimerRef.current) {
484
- clearTimeout(tooltipShowDelayTimerRef.current);
485
- }
486
- };
487
- // debounce handler to prevent call twice when
488
- // mouse enter and focus events being triggered toggether
489
- const debouncedHandleShowTooltip = debounce(handleShowTooltip, 50, true);
490
- const debouncedHandleHideTooltip = debounce(handleHideTooltip, 50, true);
491
- React.useEffect(() => {
492
- var _a, _b;
493
- const elementRefs = new Set(anchorRefs);
494
- anchorsBySelect.forEach((anchor) => {
495
- elementRefs.add({ current: anchor });
496
- });
497
- const anchorById = document.querySelector(`[id='${anchorId}']`);
498
- if (anchorById) {
499
- elementRefs.add({ current: anchorById });
500
- }
501
- const handleScrollResize = () => {
502
- handleShow(false);
503
- };
504
- const anchorScrollParent = getScrollParent(activeAnchor);
505
- const tooltipScrollParent = getScrollParent(tooltipRef.current);
506
- if (closeOnScroll) {
507
- window.addEventListener('scroll', handleScrollResize);
508
- anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.addEventListener('scroll', handleScrollResize);
509
- tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.addEventListener('scroll', handleScrollResize);
510
- }
511
- if (closeOnResize) {
512
- window.addEventListener('resize', handleScrollResize);
513
- }
514
- const handleEsc = (event) => {
515
- if (event.key !== 'Escape') {
516
- return;
517
- }
518
- handleShow(false);
519
- };
520
- if (closeOnEsc) {
521
- window.addEventListener('keydown', handleEsc);
522
- }
523
- const enabledEvents = [];
524
- if (shouldOpenOnClick) {
525
- window.addEventListener('click', handleClickOutsideAnchors);
526
- enabledEvents.push({ event: 'click', listener: handleClickTooltipAnchor });
527
- }
528
- else {
529
- enabledEvents.push({ event: 'mouseenter', listener: debouncedHandleShowTooltip }, { event: 'mouseleave', listener: debouncedHandleHideTooltip }, { event: 'focus', listener: debouncedHandleShowTooltip }, { event: 'blur', listener: debouncedHandleHideTooltip });
530
- if (float) {
531
- enabledEvents.push({
532
- event: 'mousemove',
533
- listener: handleMouseMove,
534
- });
535
- }
536
- }
537
- const handleMouseEnterTooltip = () => {
538
- hoveringTooltip.current = true;
539
- };
540
- const handleMouseLeaveTooltip = () => {
541
- hoveringTooltip.current = false;
542
- handleHideTooltip();
543
- };
544
- if (clickable && !shouldOpenOnClick) {
545
- (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('mouseenter', handleMouseEnterTooltip);
546
- (_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.addEventListener('mouseleave', handleMouseLeaveTooltip);
547
- }
548
- enabledEvents.forEach(({ event, listener }) => {
549
- elementRefs.forEach((ref) => {
550
- var _a;
551
- (_a = ref.current) === null || _a === void 0 ? void 0 : _a.addEventListener(event, listener);
552
- });
553
- });
554
- return () => {
555
- var _a, _b;
556
- if (closeOnScroll) {
557
- window.removeEventListener('scroll', handleScrollResize);
558
- anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.removeEventListener('scroll', handleScrollResize);
559
- tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.removeEventListener('scroll', handleScrollResize);
560
- }
561
- if (closeOnResize) {
562
- window.removeEventListener('resize', handleScrollResize);
563
- }
564
- if (shouldOpenOnClick) {
565
- window.removeEventListener('click', handleClickOutsideAnchors);
566
- }
567
- if (closeOnEsc) {
568
- window.removeEventListener('keydown', handleEsc);
569
- }
570
- if (clickable && !shouldOpenOnClick) {
571
- (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('mouseenter', handleMouseEnterTooltip);
572
- (_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('mouseleave', handleMouseLeaveTooltip);
573
- }
574
- enabledEvents.forEach(({ event, listener }) => {
575
- elementRefs.forEach((ref) => {
576
- var _a;
577
- (_a = ref.current) === null || _a === void 0 ? void 0 : _a.removeEventListener(event, listener);
578
- });
579
- });
580
- };
581
- /**
582
- * rendered is also a dependency to ensure anchor observers are re-registered
583
- * since `tooltipRef` becomes stale after removing/adding the tooltip to the DOM
584
- */
585
- }, [rendered, anchorRefs, anchorsBySelect, closeOnEsc, events]);
586
- React.useEffect(() => {
587
- let selector = anchorSelect !== null && anchorSelect !== void 0 ? anchorSelect : '';
588
- if (!selector && id) {
589
- selector = `[data-tooltip-id='${id}']`;
590
- }
591
- const documentObserverCallback = (mutationList) => {
592
- const newAnchors = [];
593
- mutationList.forEach((mutation) => {
594
- if (mutation.type === 'attributes' && mutation.attributeName === 'data-tooltip-id') {
595
- const newId = mutation.target.getAttribute('data-tooltip-id');
596
- if (newId === id) {
597
- newAnchors.push(mutation.target);
598
- }
599
- }
600
- if (mutation.type !== 'childList') {
601
- return;
602
- }
603
- if (activeAnchor) {
604
- [...mutation.removedNodes].some((node) => {
605
- var _a;
606
- if ((_a = node === null || node === void 0 ? void 0 : node.contains) === null || _a === void 0 ? void 0 : _a.call(node, activeAnchor)) {
607
- setRendered(false);
608
- handleShow(false);
609
- setActiveAnchor(null);
610
- if (tooltipShowDelayTimerRef.current) {
611
- clearTimeout(tooltipShowDelayTimerRef.current);
612
- }
613
- if (tooltipHideDelayTimerRef.current) {
614
- clearTimeout(tooltipHideDelayTimerRef.current);
615
- }
616
- return true;
617
- }
618
- return false;
619
- });
620
- }
621
- if (!selector) {
622
- return;
623
- }
624
- try {
625
- const elements = [...mutation.addedNodes].filter((node) => node.nodeType === 1);
626
- newAnchors.push(
627
- // the element itself is an anchor
628
- ...elements.filter((element) => element.matches(selector)));
629
- newAnchors.push(
630
- // the element has children which are anchors
631
- ...elements.flatMap((element) => [...element.querySelectorAll(selector)]));
632
- }
633
- catch (_a) {
634
- /**
635
- * invalid CSS selector.
636
- * already warned on tooltip controller
637
- */
638
- }
639
- });
640
- if (newAnchors.length) {
641
- setAnchorsBySelect((anchors) => [...anchors, ...newAnchors]);
642
- }
643
- };
644
- const documentObserver = new MutationObserver(documentObserverCallback);
645
- // watch for anchor being removed from the DOM
646
- documentObserver.observe(document.body, {
647
- childList: true,
648
- subtree: true,
649
- attributes: true,
650
- attributeFilter: ['data-tooltip-id'],
651
- });
652
- return () => {
653
- documentObserver.disconnect();
654
- };
655
- }, [id, anchorSelect, activeAnchor]);
656
- const updateTooltipPosition = () => {
657
- if (position) {
658
- // if `position` is set, override regular and `float` positioning
659
- handleTooltipPosition(position);
660
- return;
661
- }
662
- if (float) {
663
- if (lastFloatPosition.current) {
664
- /*
665
- Without this, changes to `content`, `place`, `offset`, ..., will only
666
- trigger a position calculation after a `mousemove` event.
667
-
668
- To see why this matters, comment this line, run `yarn dev` and click the
669
- "Hover me!" anchor.
670
- */
671
- handleTooltipPosition(lastFloatPosition.current);
672
- }
673
- // if `float` is set, override regular positioning
674
- return;
675
- }
676
- computeTooltipPosition({
677
- place,
678
- offset,
679
- elementReference: activeAnchor,
680
- tooltipReference: tooltipRef.current,
681
- tooltipArrowReference: tooltipArrowRef.current,
682
- strategy: positionStrategy,
683
- middlewares,
684
- }).then((computedStylesData) => {
685
- if (!mounted.current) {
686
- // invalidate computed positions after remount
687
- return;
688
- }
689
- if (Object.keys(computedStylesData.tooltipStyles).length) {
690
- setInlineStyles(computedStylesData.tooltipStyles);
691
- }
692
- if (Object.keys(computedStylesData.tooltipArrowStyles).length) {
693
- setInlineArrowStyles(computedStylesData.tooltipArrowStyles);
694
- }
695
- setActualPlacement(computedStylesData.place);
696
- });
697
- };
698
- React.useEffect(() => {
699
- updateTooltipPosition();
700
- }, [show, activeAnchor, content, externalStyles, place, offset, positionStrategy, position]);
701
- React.useEffect(() => {
702
- if (!(contentWrapperRef === null || contentWrapperRef === void 0 ? void 0 : contentWrapperRef.current)) {
703
- return () => null;
704
- }
705
- const contentObserver = new ResizeObserver(() => {
706
- updateTooltipPosition();
707
- });
708
- contentObserver.observe(contentWrapperRef.current);
709
- return () => {
710
- contentObserver.disconnect();
711
- };
712
- }, [content, contentWrapperRef === null || contentWrapperRef === void 0 ? void 0 : contentWrapperRef.current]);
713
- React.useEffect(() => {
714
- var _a;
715
- const anchorById = document.querySelector(`[id='${anchorId}']`);
716
- const anchors = [...anchorsBySelect, anchorById];
717
- if (!activeAnchor || !anchors.includes(activeAnchor)) {
718
- /**
719
- * if there is no active anchor,
720
- * or if the current active anchor is not amongst the allowed ones,
721
- * reset it
722
- */
723
- setActiveAnchor((_a = anchorsBySelect[0]) !== null && _a !== void 0 ? _a : anchorById);
724
- }
725
- }, [anchorId, anchorsBySelect, activeAnchor]);
726
- React.useEffect(() => {
727
- return () => {
728
- if (tooltipShowDelayTimerRef.current) {
729
- clearTimeout(tooltipShowDelayTimerRef.current);
730
- }
731
- if (tooltipHideDelayTimerRef.current) {
732
- clearTimeout(tooltipHideDelayTimerRef.current);
733
- }
734
- };
735
- }, []);
736
- React.useEffect(() => {
737
- let selector = anchorSelect;
738
- if (!selector && id) {
739
- selector = `[data-tooltip-id='${id}']`;
740
- }
741
- if (!selector) {
742
- return;
743
- }
744
- try {
745
- const anchors = Array.from(document.querySelectorAll(selector));
746
- setAnchorsBySelect(anchors);
747
- }
748
- catch (_a) {
749
- // warning was already issued in the controller
750
- setAnchorsBySelect([]);
751
- }
752
- }, [id, anchorSelect]);
753
- const canShow = !hidden && content && show && Object.keys(inlineStyles).length > 0;
754
- return rendered ? (React__default["default"].createElement(WrapperElement, { id: id, role: "tooltip", className: classNames__default["default"]('react-tooltip', styles['tooltip'], styles[variant], className, `react-tooltip__place-${actualPlacement}`, {
755
- [styles['show']]: canShow,
756
- [styles['fixed']]: positionStrategy === 'fixed',
757
- [styles['clickable']]: clickable,
758
- }), style: { ...externalStyles, ...inlineStyles }, ref: tooltipRef },
759
- content,
760
- React__default["default"].createElement(WrapperElement, { className: classNames__default["default"]('react-tooltip-arrow', styles['arrow'], classNameArrow, {
761
- /**
762
- * changed from dash `no-arrow` to camelcase because of:
763
- * https://github.com/indooorsman/esbuild-css-modules-plugin/issues/42
764
- */
765
- [styles['noArrow']]: noArrow,
766
- }), style: inlineArrowStyles, ref: tooltipArrowRef }))) : null;
767
- };
768
-
769
- /* eslint-disable react/no-danger */
770
- const TooltipContent = ({ content }) => {
771
- return React__default["default"].createElement("span", { dangerouslySetInnerHTML: { __html: content } });
772
- };
773
-
774
- 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, setIsOpen, afterShow, afterHide, }) => {
775
- const [tooltipContent, setTooltipContent] = React.useState(content);
776
- const [tooltipHtml, setTooltipHtml] = React.useState(html);
777
- const [tooltipPlace, setTooltipPlace] = React.useState(place);
778
- const [tooltipVariant, setTooltipVariant] = React.useState(variant);
779
- const [tooltipOffset, setTooltipOffset] = React.useState(offset);
780
- const [tooltipDelayShow, setTooltipDelayShow] = React.useState(delayShow);
781
- const [tooltipDelayHide, setTooltipDelayHide] = React.useState(delayHide);
782
- const [tooltipFloat, setTooltipFloat] = React.useState(float);
783
- const [tooltipHidden, setTooltipHidden] = React.useState(hidden);
784
- const [tooltipWrapper, setTooltipWrapper] = React.useState(wrapper);
785
- const [tooltipEvents, setTooltipEvents] = React.useState(events);
786
- const [tooltipPositionStrategy, setTooltipPositionStrategy] = React.useState(positionStrategy);
787
- const [activeAnchor, setActiveAnchor] = React.useState(null);
788
- /**
789
- * @todo Remove this in a future version (provider/wrapper method is deprecated)
790
- */
791
- const { anchorRefs, activeAnchor: providerActiveAnchor } = useTooltip(id);
792
- const getDataAttributesFromAnchorElement = (elementReference) => {
793
- const dataAttributes = elementReference === null || elementReference === void 0 ? void 0 : elementReference.getAttributeNames().reduce((acc, name) => {
794
- var _a;
795
- if (name.startsWith('data-tooltip-')) {
796
- const parsedAttribute = name.replace(/^data-tooltip-/, '');
797
- acc[parsedAttribute] = (_a = elementReference === null || elementReference === void 0 ? void 0 : elementReference.getAttribute(name)) !== null && _a !== void 0 ? _a : null;
798
- }
799
- return acc;
800
- }, {});
801
- return dataAttributes;
802
- };
803
- const applyAllDataAttributesFromAnchorElement = (dataAttributes) => {
804
- const handleDataAttributes = {
805
- place: (value) => {
806
- var _a;
807
- setTooltipPlace((_a = value) !== null && _a !== void 0 ? _a : place);
808
- },
809
- content: (value) => {
810
- setTooltipContent(value !== null && value !== void 0 ? value : content);
811
- },
812
- html: (value) => {
813
- setTooltipHtml(value !== null && value !== void 0 ? value : html);
814
- },
815
- variant: (value) => {
816
- var _a;
817
- setTooltipVariant((_a = value) !== null && _a !== void 0 ? _a : variant);
818
- },
819
- offset: (value) => {
820
- setTooltipOffset(value === null ? offset : Number(value));
821
- },
822
- wrapper: (value) => {
823
- var _a;
824
- setTooltipWrapper((_a = value) !== null && _a !== void 0 ? _a : wrapper);
825
- },
826
- events: (value) => {
827
- const parsed = value === null || value === void 0 ? void 0 : value.split(' ');
828
- setTooltipEvents(parsed !== null && parsed !== void 0 ? parsed : events);
829
- },
830
- 'position-strategy': (value) => {
831
- var _a;
832
- setTooltipPositionStrategy((_a = value) !== null && _a !== void 0 ? _a : positionStrategy);
833
- },
834
- 'delay-show': (value) => {
835
- setTooltipDelayShow(value === null ? delayShow : Number(value));
836
- },
837
- 'delay-hide': (value) => {
838
- setTooltipDelayHide(value === null ? delayHide : Number(value));
839
- },
840
- float: (value) => {
841
- setTooltipFloat(value === null ? float : value === 'true');
842
- },
843
- hidden: (value) => {
844
- setTooltipHidden(value === null ? hidden : value === 'true');
845
- },
846
- };
847
- // reset unset data attributes to default values
848
- // without this, data attributes from the last active anchor will still be used
849
- Object.values(handleDataAttributes).forEach((handler) => handler(null));
850
- Object.entries(dataAttributes).forEach(([key, value]) => {
851
- var _a;
852
- (_a = handleDataAttributes[key]) === null || _a === void 0 ? void 0 : _a.call(handleDataAttributes, value);
853
- });
854
- };
855
- React.useEffect(() => {
856
- setTooltipContent(content);
857
- }, [content]);
858
- React.useEffect(() => {
859
- setTooltipHtml(html);
860
- }, [html]);
861
- React.useEffect(() => {
862
- setTooltipPlace(place);
863
- }, [place]);
864
- React.useEffect(() => {
865
- setTooltipVariant(variant);
866
- }, [variant]);
867
- React.useEffect(() => {
868
- setTooltipOffset(offset);
869
- }, [offset]);
870
- React.useEffect(() => {
871
- setTooltipDelayShow(delayShow);
872
- }, [delayShow]);
873
- React.useEffect(() => {
874
- setTooltipDelayHide(delayHide);
875
- }, [delayHide]);
876
- React.useEffect(() => {
877
- setTooltipFloat(float);
878
- }, [float]);
879
- React.useEffect(() => {
880
- setTooltipHidden(hidden);
881
- }, [hidden]);
882
- React.useEffect(() => {
883
- setTooltipPositionStrategy(positionStrategy);
884
- }, [positionStrategy]);
885
- React.useEffect(() => {
886
- var _a;
887
- const elementRefs = new Set(anchorRefs);
888
- let selector = anchorSelect;
889
- if (!selector && id) {
890
- selector = `[data-tooltip-id='${id}']`;
891
- }
892
- if (selector) {
893
- try {
894
- const anchorsBySelect = document.querySelectorAll(selector);
895
- anchorsBySelect.forEach((anchor) => {
896
- elementRefs.add({ current: anchor });
897
- });
898
- }
899
- catch (_b) {
900
- {
901
- // eslint-disable-next-line no-console
902
- console.warn(`[react-tooltip] "${selector}" is not a valid CSS selector`);
903
- }
904
- }
905
- }
906
- const anchorById = document.querySelector(`[id='${anchorId}']`);
907
- if (anchorById) {
908
- elementRefs.add({ current: anchorById });
909
- }
910
- if (!elementRefs.size) {
911
- return () => null;
912
- }
913
- const anchorElement = (_a = activeAnchor !== null && activeAnchor !== void 0 ? activeAnchor : anchorById) !== null && _a !== void 0 ? _a : providerActiveAnchor.current;
914
- const observerCallback = (mutationList) => {
915
- mutationList.forEach((mutation) => {
916
- var _a;
917
- if (!anchorElement ||
918
- mutation.type !== 'attributes' ||
919
- !((_a = mutation.attributeName) === null || _a === void 0 ? void 0 : _a.startsWith('data-tooltip-'))) {
920
- return;
921
- }
922
- // make sure to get all set attributes, since all unset attributes are reset
923
- const dataAttributes = getDataAttributesFromAnchorElement(anchorElement);
924
- applyAllDataAttributesFromAnchorElement(dataAttributes);
925
- });
926
- };
927
- // Create an observer instance linked to the callback function
928
- const observer = new MutationObserver(observerCallback);
929
- // do not check for subtree and childrens, we only want to know attribute changes
930
- // to stay watching `data-attributes-*` from anchor element
931
- const observerConfig = { attributes: true, childList: false, subtree: false };
932
- if (anchorElement) {
933
- const dataAttributes = getDataAttributesFromAnchorElement(anchorElement);
934
- applyAllDataAttributesFromAnchorElement(dataAttributes);
935
- // Start observing the target node for configured mutations
936
- observer.observe(anchorElement, observerConfig);
937
- }
938
- return () => {
939
- // Remove the observer when the tooltip is destroyed
940
- observer.disconnect();
941
- };
942
- }, [anchorRefs, providerActiveAnchor, activeAnchor, anchorId, anchorSelect]);
943
- /**
944
- * content priority: children < render or content < html
945
- * children should be lower priority so that it can be used as the "default" content
946
- */
947
- let renderedContent = children;
948
- const contentWrapperRef = React.useRef(null);
949
- if (render) {
950
- const rendered = render({ content: tooltipContent !== null && tooltipContent !== void 0 ? tooltipContent : null, activeAnchor });
951
- renderedContent = rendered ? (React__default["default"].createElement("div", { ref: contentWrapperRef, className: "react-tooltip-content-wrapper" }, rendered)) : null;
952
- }
953
- else if (tooltipContent) {
954
- renderedContent = tooltipContent;
955
- }
956
- if (tooltipHtml) {
957
- renderedContent = React__default["default"].createElement(TooltipContent, { content: tooltipHtml });
958
- }
959
- const props = {
960
- id,
961
- anchorId,
962
- anchorSelect,
963
- className,
964
- classNameArrow,
965
- content: renderedContent,
966
- contentWrapperRef,
967
- place: tooltipPlace,
968
- variant: tooltipVariant,
969
- offset: tooltipOffset,
970
- wrapper: tooltipWrapper,
971
- events: tooltipEvents,
972
- openOnClick,
973
- positionStrategy: tooltipPositionStrategy,
974
- middlewares,
975
- delayShow: tooltipDelayShow,
976
- delayHide: tooltipDelayHide,
977
- float: tooltipFloat,
978
- hidden: tooltipHidden,
979
- noArrow,
980
- clickable,
981
- closeOnEsc,
982
- closeOnScroll,
983
- closeOnResize,
984
- style,
985
- position,
986
- isOpen,
987
- setIsOpen,
988
- afterShow,
989
- afterHide,
990
- activeAnchor,
991
- setActiveAnchor: (anchor) => setActiveAnchor(anchor),
992
- };
993
- return React__default["default"].createElement(Tooltip, { ...props });
994
- };
995
-
996
- exports.Tooltip = TooltipController;
997
- exports.TooltipProvider = TooltipProvider;
998
- exports.TooltipWrapper = TooltipWrapper;
999
-
1000
- Object.defineProperty(exports, '__esModule', { value: true });
189
+ /**
190
+ * @deprecated Use the `data-tooltip-id` attribute, or the `anchorSelect` prop instead.
191
+ * See https://react-tooltip.com/docs/getting-started
192
+ */
193
+ const TooltipWrapper = ({ tooltipId, children, className, place, content, html, variant, offset, wrapper, events, positionStrategy, delayShow, delayHide, }) => {
194
+ const { attach, detach } = useTooltip(tooltipId);
195
+ const anchorRef = React.useRef(null);
196
+ React.useEffect(() => {
197
+ attach(anchorRef);
198
+ return () => {
199
+ detach(anchorRef);
200
+ };
201
+ }, []);
202
+ 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));
203
+ };
204
+
205
+ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
206
+
207
+ const isScrollable = (node) => {
208
+ if (!(node instanceof HTMLElement || node instanceof SVGElement)) {
209
+ return false;
210
+ }
211
+ const style = getComputedStyle(node);
212
+ return ['overflow', 'overflow-x', 'overflow-y'].some((propertyName) => {
213
+ const value = style.getPropertyValue(propertyName);
214
+ return value === 'auto' || value === 'scroll';
215
+ });
216
+ };
217
+ const getScrollParent = (node) => {
218
+ if (!node) {
219
+ return null;
220
+ }
221
+ let currentParent = node.parentElement;
222
+ while (currentParent) {
223
+ if (isScrollable(currentParent)) {
224
+ return currentParent;
225
+ }
226
+ currentParent = currentParent.parentElement;
227
+ }
228
+ return document.scrollingElement || document.documentElement;
229
+ };
230
+
231
+ const computeTooltipPosition = async ({ elementReference = null, tooltipReference = null, tooltipArrowReference = null, place = 'top', offset: offsetValue = 10, strategy = 'absolute', middlewares = [dom.offset(Number(offsetValue)), dom.flip(), dom.shift({ padding: 5 })], }) => {
232
+ if (!elementReference) {
233
+ // elementReference can be null or undefined and we will not compute the position
234
+ // eslint-disable-next-line no-console
235
+ // console.error('The reference element for tooltip was not defined: ', elementReference)
236
+ return { tooltipStyles: {}, tooltipArrowStyles: {}, place };
237
+ }
238
+ if (tooltipReference === null) {
239
+ return { tooltipStyles: {}, tooltipArrowStyles: {}, place };
240
+ }
241
+ const middleware = middlewares;
242
+ if (tooltipArrowReference) {
243
+ middleware.push(dom.arrow({ element: tooltipArrowReference, padding: 5 }));
244
+ return dom.computePosition(elementReference, tooltipReference, {
245
+ placement: place,
246
+ strategy,
247
+ middleware,
248
+ }).then(({ x, y, placement, middlewareData }) => {
249
+ var _a, _b;
250
+ const styles = { left: `${x}px`, top: `${y}px` };
251
+ const { x: arrowX, y: arrowY } = (_a = middlewareData.arrow) !== null && _a !== void 0 ? _a : { x: 0, y: 0 };
252
+ const staticSide = (_b = {
253
+ top: 'bottom',
254
+ right: 'left',
255
+ bottom: 'top',
256
+ left: 'right',
257
+ }[placement.split('-')[0]]) !== null && _b !== void 0 ? _b : 'bottom';
258
+ const arrowStyle = {
259
+ left: arrowX != null ? `${arrowX}px` : '',
260
+ top: arrowY != null ? `${arrowY}px` : '',
261
+ right: '',
262
+ bottom: '',
263
+ [staticSide]: '-4px',
264
+ };
265
+ return { tooltipStyles: styles, tooltipArrowStyles: arrowStyle, place: placement };
266
+ });
267
+ }
268
+ return dom.computePosition(elementReference, tooltipReference, {
269
+ placement: 'bottom',
270
+ strategy,
271
+ middleware,
272
+ }).then(({ x, y, placement }) => {
273
+ const styles = { left: `${x}px`, top: `${y}px` };
274
+ return { tooltipStyles: styles, tooltipArrowStyles: {}, place: placement };
275
+ });
276
+ };
277
+
278
+ 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"};
279
+
280
+ var styles = {"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"};
281
+
282
+ const Tooltip = ({
283
+ // props
284
+ 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,
285
+ // props handled by controller
286
+ content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, }) => {
287
+ const tooltipRef = React.useRef(null);
288
+ const tooltipArrowRef = React.useRef(null);
289
+ const tooltipShowDelayTimerRef = React.useRef(null);
290
+ const tooltipHideDelayTimerRef = React.useRef(null);
291
+ const [actualPlacement, setActualPlacement] = React.useState(place);
292
+ const [inlineStyles, setInlineStyles] = React.useState({});
293
+ const [inlineArrowStyles, setInlineArrowStyles] = React.useState({});
294
+ const [show, setShow] = React.useState(false);
295
+ const [rendered, setRendered] = React.useState(false);
296
+ const wasShowing = React.useRef(false);
297
+ const lastFloatPosition = React.useRef(null);
298
+ /**
299
+ * @todo Remove this in a future version (provider/wrapper method is deprecated)
300
+ */
301
+ const { anchorRefs, setActiveAnchor: setProviderActiveAnchor } = useTooltip(id);
302
+ const hoveringTooltip = React.useRef(false);
303
+ const [anchorsBySelect, setAnchorsBySelect] = React.useState([]);
304
+ const mounted = React.useRef(false);
305
+ const shouldOpenOnClick = openOnClick || events.includes('click');
306
+ /**
307
+ * useLayoutEffect runs before useEffect,
308
+ * but should be used carefully because of caveats
309
+ * https://beta.reactjs.org/reference/react/useLayoutEffect#caveats
310
+ */
311
+ useIsomorphicLayoutEffect(() => {
312
+ mounted.current = true;
313
+ return () => {
314
+ mounted.current = false;
315
+ };
316
+ }, []);
317
+ React.useEffect(() => {
318
+ if (!show) {
319
+ /**
320
+ * this fixes weird behavior when switching between two anchor elements very quickly
321
+ * remove the timeout and switch quickly between two adjancent anchor elements to see it
322
+ *
323
+ * in practice, this means the tooltip is not immediately removed from the DOM on hide
324
+ */
325
+ const timeout = setTimeout(() => {
326
+ setRendered(false);
327
+ }, 150);
328
+ return () => {
329
+ clearTimeout(timeout);
330
+ };
331
+ }
332
+ return () => null;
333
+ }, [show]);
334
+ const handleShow = (value) => {
335
+ if (!mounted.current) {
336
+ return;
337
+ }
338
+ if (value) {
339
+ setRendered(true);
340
+ }
341
+ /**
342
+ * wait for the component to render and calculate position
343
+ * before actually showing
344
+ */
345
+ setTimeout(() => {
346
+ if (!mounted.current) {
347
+ return;
348
+ }
349
+ setIsOpen === null || setIsOpen === void 0 ? void 0 : setIsOpen(value);
350
+ if (isOpen === undefined) {
351
+ setShow(value);
352
+ }
353
+ }, 10);
354
+ };
355
+ /**
356
+ * this replicates the effect from `handleShow()`
357
+ * when `isOpen` is changed from outside
358
+ */
359
+ React.useEffect(() => {
360
+ if (isOpen === undefined) {
361
+ return () => null;
362
+ }
363
+ if (isOpen) {
364
+ setRendered(true);
365
+ }
366
+ const timeout = setTimeout(() => {
367
+ setShow(isOpen);
368
+ }, 10);
369
+ return () => {
370
+ clearTimeout(timeout);
371
+ };
372
+ }, [isOpen]);
373
+ React.useEffect(() => {
374
+ if (show === wasShowing.current) {
375
+ return;
376
+ }
377
+ wasShowing.current = show;
378
+ if (show) {
379
+ afterShow === null || afterShow === void 0 ? void 0 : afterShow();
380
+ }
381
+ else {
382
+ afterHide === null || afterHide === void 0 ? void 0 : afterHide();
383
+ }
384
+ }, [show]);
385
+ const handleShowTooltipDelayed = () => {
386
+ if (tooltipShowDelayTimerRef.current) {
387
+ clearTimeout(tooltipShowDelayTimerRef.current);
388
+ }
389
+ tooltipShowDelayTimerRef.current = setTimeout(() => {
390
+ handleShow(true);
391
+ }, delayShow);
392
+ };
393
+ const handleHideTooltipDelayed = (delay = delayHide) => {
394
+ if (tooltipHideDelayTimerRef.current) {
395
+ clearTimeout(tooltipHideDelayTimerRef.current);
396
+ }
397
+ tooltipHideDelayTimerRef.current = setTimeout(() => {
398
+ if (hoveringTooltip.current) {
399
+ return;
400
+ }
401
+ handleShow(false);
402
+ }, delay);
403
+ };
404
+ const handleShowTooltip = (event) => {
405
+ var _a;
406
+ if (!event) {
407
+ return;
408
+ }
409
+ const target = ((_a = event.currentTarget) !== null && _a !== void 0 ? _a : event.target);
410
+ if (!(target === null || target === void 0 ? void 0 : target.isConnected)) {
411
+ /**
412
+ * this happens when the target is removed from the DOM
413
+ * at the same time the tooltip gets triggered
414
+ */
415
+ setActiveAnchor(null);
416
+ setProviderActiveAnchor({ current: null });
417
+ return;
418
+ }
419
+ if (delayShow) {
420
+ handleShowTooltipDelayed();
421
+ }
422
+ else {
423
+ handleShow(true);
424
+ }
425
+ setActiveAnchor(target);
426
+ setProviderActiveAnchor({ current: target });
427
+ if (tooltipHideDelayTimerRef.current) {
428
+ clearTimeout(tooltipHideDelayTimerRef.current);
429
+ }
430
+ };
431
+ const handleHideTooltip = () => {
432
+ if (clickable) {
433
+ // allow time for the mouse to reach the tooltip, in case there's a gap
434
+ handleHideTooltipDelayed(delayHide || 100);
435
+ }
436
+ else if (delayHide) {
437
+ handleHideTooltipDelayed();
438
+ }
439
+ else {
440
+ handleShow(false);
441
+ }
442
+ if (tooltipShowDelayTimerRef.current) {
443
+ clearTimeout(tooltipShowDelayTimerRef.current);
444
+ }
445
+ };
446
+ const handleTooltipPosition = ({ x, y }) => {
447
+ const virtualElement = {
448
+ getBoundingClientRect() {
449
+ return {
450
+ x,
451
+ y,
452
+ width: 0,
453
+ height: 0,
454
+ top: y,
455
+ left: x,
456
+ right: x,
457
+ bottom: y,
458
+ };
459
+ },
460
+ };
461
+ computeTooltipPosition({
462
+ place,
463
+ offset,
464
+ elementReference: virtualElement,
465
+ tooltipReference: tooltipRef.current,
466
+ tooltipArrowReference: tooltipArrowRef.current,
467
+ strategy: positionStrategy,
468
+ middlewares,
469
+ }).then((computedStylesData) => {
470
+ if (Object.keys(computedStylesData.tooltipStyles).length) {
471
+ setInlineStyles(computedStylesData.tooltipStyles);
472
+ }
473
+ if (Object.keys(computedStylesData.tooltipArrowStyles).length) {
474
+ setInlineArrowStyles(computedStylesData.tooltipArrowStyles);
475
+ }
476
+ setActualPlacement(computedStylesData.place);
477
+ });
478
+ };
479
+ const handleMouseMove = (event) => {
480
+ if (!event) {
481
+ return;
482
+ }
483
+ const mouseEvent = event;
484
+ const mousePosition = {
485
+ x: mouseEvent.clientX,
486
+ y: mouseEvent.clientY,
487
+ };
488
+ handleTooltipPosition(mousePosition);
489
+ lastFloatPosition.current = mousePosition;
490
+ };
491
+ const handleClickTooltipAnchor = (event) => {
492
+ handleShowTooltip(event);
493
+ if (delayHide) {
494
+ handleHideTooltipDelayed();
495
+ }
496
+ };
497
+ const handleClickOutsideAnchors = (event) => {
498
+ var _a;
499
+ const anchorById = document.querySelector(`[id='${anchorId}']`);
500
+ const anchors = [anchorById, ...anchorsBySelect];
501
+ if (anchors.some((anchor) => anchor === null || anchor === void 0 ? void 0 : anchor.contains(event.target))) {
502
+ return;
503
+ }
504
+ if ((_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) {
505
+ return;
506
+ }
507
+ handleShow(false);
508
+ if (tooltipShowDelayTimerRef.current) {
509
+ clearTimeout(tooltipShowDelayTimerRef.current);
510
+ }
511
+ };
512
+ // debounce handler to prevent call twice when
513
+ // mouse enter and focus events being triggered toggether
514
+ const debouncedHandleShowTooltip = debounce(handleShowTooltip, 50, true);
515
+ const debouncedHandleHideTooltip = debounce(handleHideTooltip, 50, true);
516
+ React.useEffect(() => {
517
+ var _a, _b;
518
+ const elementRefs = new Set(anchorRefs);
519
+ anchorsBySelect.forEach((anchor) => {
520
+ elementRefs.add({ current: anchor });
521
+ });
522
+ const anchorById = document.querySelector(`[id='${anchorId}']`);
523
+ if (anchorById) {
524
+ elementRefs.add({ current: anchorById });
525
+ }
526
+ const handleScrollResize = () => {
527
+ handleShow(false);
528
+ };
529
+ const anchorScrollParent = getScrollParent(activeAnchor);
530
+ const tooltipScrollParent = getScrollParent(tooltipRef.current);
531
+ if (closeOnScroll) {
532
+ window.addEventListener('scroll', handleScrollResize);
533
+ anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.addEventListener('scroll', handleScrollResize);
534
+ tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.addEventListener('scroll', handleScrollResize);
535
+ }
536
+ if (closeOnResize) {
537
+ window.addEventListener('resize', handleScrollResize);
538
+ }
539
+ const handleEsc = (event) => {
540
+ if (event.key !== 'Escape') {
541
+ return;
542
+ }
543
+ handleShow(false);
544
+ };
545
+ if (closeOnEsc) {
546
+ window.addEventListener('keydown', handleEsc);
547
+ }
548
+ const enabledEvents = [];
549
+ if (shouldOpenOnClick) {
550
+ window.addEventListener('click', handleClickOutsideAnchors);
551
+ enabledEvents.push({ event: 'click', listener: handleClickTooltipAnchor });
552
+ }
553
+ else {
554
+ enabledEvents.push({ event: 'mouseenter', listener: debouncedHandleShowTooltip }, { event: 'mouseleave', listener: debouncedHandleHideTooltip }, { event: 'focus', listener: debouncedHandleShowTooltip }, { event: 'blur', listener: debouncedHandleHideTooltip });
555
+ if (float) {
556
+ enabledEvents.push({
557
+ event: 'mousemove',
558
+ listener: handleMouseMove,
559
+ });
560
+ }
561
+ }
562
+ const handleMouseEnterTooltip = () => {
563
+ hoveringTooltip.current = true;
564
+ };
565
+ const handleMouseLeaveTooltip = () => {
566
+ hoveringTooltip.current = false;
567
+ handleHideTooltip();
568
+ };
569
+ if (clickable && !shouldOpenOnClick) {
570
+ (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('mouseenter', handleMouseEnterTooltip);
571
+ (_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.addEventListener('mouseleave', handleMouseLeaveTooltip);
572
+ }
573
+ enabledEvents.forEach(({ event, listener }) => {
574
+ elementRefs.forEach((ref) => {
575
+ var _a;
576
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.addEventListener(event, listener);
577
+ });
578
+ });
579
+ return () => {
580
+ var _a, _b;
581
+ if (closeOnScroll) {
582
+ window.removeEventListener('scroll', handleScrollResize);
583
+ anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.removeEventListener('scroll', handleScrollResize);
584
+ tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.removeEventListener('scroll', handleScrollResize);
585
+ }
586
+ if (closeOnResize) {
587
+ window.removeEventListener('resize', handleScrollResize);
588
+ }
589
+ if (shouldOpenOnClick) {
590
+ window.removeEventListener('click', handleClickOutsideAnchors);
591
+ }
592
+ if (closeOnEsc) {
593
+ window.removeEventListener('keydown', handleEsc);
594
+ }
595
+ if (clickable && !shouldOpenOnClick) {
596
+ (_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('mouseenter', handleMouseEnterTooltip);
597
+ (_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('mouseleave', handleMouseLeaveTooltip);
598
+ }
599
+ enabledEvents.forEach(({ event, listener }) => {
600
+ elementRefs.forEach((ref) => {
601
+ var _a;
602
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.removeEventListener(event, listener);
603
+ });
604
+ });
605
+ };
606
+ /**
607
+ * rendered is also a dependency to ensure anchor observers are re-registered
608
+ * since `tooltipRef` becomes stale after removing/adding the tooltip to the DOM
609
+ */
610
+ }, [rendered, anchorRefs, anchorsBySelect, closeOnEsc, events]);
611
+ React.useEffect(() => {
612
+ let selector = anchorSelect !== null && anchorSelect !== void 0 ? anchorSelect : '';
613
+ if (!selector && id) {
614
+ selector = `[data-tooltip-id='${id}']`;
615
+ }
616
+ const documentObserverCallback = (mutationList) => {
617
+ const newAnchors = [];
618
+ mutationList.forEach((mutation) => {
619
+ if (mutation.type === 'attributes' && mutation.attributeName === 'data-tooltip-id') {
620
+ const newId = mutation.target.getAttribute('data-tooltip-id');
621
+ if (newId === id) {
622
+ newAnchors.push(mutation.target);
623
+ }
624
+ }
625
+ if (mutation.type !== 'childList') {
626
+ return;
627
+ }
628
+ if (activeAnchor) {
629
+ [...mutation.removedNodes].some((node) => {
630
+ var _a;
631
+ if ((_a = node === null || node === void 0 ? void 0 : node.contains) === null || _a === void 0 ? void 0 : _a.call(node, activeAnchor)) {
632
+ setRendered(false);
633
+ handleShow(false);
634
+ setActiveAnchor(null);
635
+ if (tooltipShowDelayTimerRef.current) {
636
+ clearTimeout(tooltipShowDelayTimerRef.current);
637
+ }
638
+ if (tooltipHideDelayTimerRef.current) {
639
+ clearTimeout(tooltipHideDelayTimerRef.current);
640
+ }
641
+ return true;
642
+ }
643
+ return false;
644
+ });
645
+ }
646
+ if (!selector) {
647
+ return;
648
+ }
649
+ try {
650
+ const elements = [...mutation.addedNodes].filter((node) => node.nodeType === 1);
651
+ newAnchors.push(
652
+ // the element itself is an anchor
653
+ ...elements.filter((element) => element.matches(selector)));
654
+ newAnchors.push(
655
+ // the element has children which are anchors
656
+ ...elements.flatMap((element) => [...element.querySelectorAll(selector)]));
657
+ }
658
+ catch (_a) {
659
+ /**
660
+ * invalid CSS selector.
661
+ * already warned on tooltip controller
662
+ */
663
+ }
664
+ });
665
+ if (newAnchors.length) {
666
+ setAnchorsBySelect((anchors) => [...anchors, ...newAnchors]);
667
+ }
668
+ };
669
+ const documentObserver = new MutationObserver(documentObserverCallback);
670
+ // watch for anchor being removed from the DOM
671
+ documentObserver.observe(document.body, {
672
+ childList: true,
673
+ subtree: true,
674
+ attributes: true,
675
+ attributeFilter: ['data-tooltip-id'],
676
+ });
677
+ return () => {
678
+ documentObserver.disconnect();
679
+ };
680
+ }, [id, anchorSelect, activeAnchor]);
681
+ const updateTooltipPosition = () => {
682
+ if (position) {
683
+ // if `position` is set, override regular and `float` positioning
684
+ handleTooltipPosition(position);
685
+ return;
686
+ }
687
+ if (float) {
688
+ if (lastFloatPosition.current) {
689
+ /*
690
+ Without this, changes to `content`, `place`, `offset`, ..., will only
691
+ trigger a position calculation after a `mousemove` event.
692
+
693
+ To see why this matters, comment this line, run `yarn dev` and click the
694
+ "Hover me!" anchor.
695
+ */
696
+ handleTooltipPosition(lastFloatPosition.current);
697
+ }
698
+ // if `float` is set, override regular positioning
699
+ return;
700
+ }
701
+ computeTooltipPosition({
702
+ place,
703
+ offset,
704
+ elementReference: activeAnchor,
705
+ tooltipReference: tooltipRef.current,
706
+ tooltipArrowReference: tooltipArrowRef.current,
707
+ strategy: positionStrategy,
708
+ middlewares,
709
+ }).then((computedStylesData) => {
710
+ if (!mounted.current) {
711
+ // invalidate computed positions after remount
712
+ return;
713
+ }
714
+ if (Object.keys(computedStylesData.tooltipStyles).length) {
715
+ setInlineStyles(computedStylesData.tooltipStyles);
716
+ }
717
+ if (Object.keys(computedStylesData.tooltipArrowStyles).length) {
718
+ setInlineArrowStyles(computedStylesData.tooltipArrowStyles);
719
+ }
720
+ setActualPlacement(computedStylesData.place);
721
+ });
722
+ };
723
+ React.useEffect(() => {
724
+ updateTooltipPosition();
725
+ }, [show, activeAnchor, content, externalStyles, place, offset, positionStrategy, position]);
726
+ React.useEffect(() => {
727
+ if (!(contentWrapperRef === null || contentWrapperRef === void 0 ? void 0 : contentWrapperRef.current)) {
728
+ return () => null;
729
+ }
730
+ const contentObserver = new ResizeObserver(() => {
731
+ updateTooltipPosition();
732
+ });
733
+ contentObserver.observe(contentWrapperRef.current);
734
+ return () => {
735
+ contentObserver.disconnect();
736
+ };
737
+ }, [content, contentWrapperRef === null || contentWrapperRef === void 0 ? void 0 : contentWrapperRef.current]);
738
+ React.useEffect(() => {
739
+ var _a;
740
+ const anchorById = document.querySelector(`[id='${anchorId}']`);
741
+ const anchors = [...anchorsBySelect, anchorById];
742
+ if (!activeAnchor || !anchors.includes(activeAnchor)) {
743
+ /**
744
+ * if there is no active anchor,
745
+ * or if the current active anchor is not amongst the allowed ones,
746
+ * reset it
747
+ */
748
+ setActiveAnchor((_a = anchorsBySelect[0]) !== null && _a !== void 0 ? _a : anchorById);
749
+ }
750
+ }, [anchorId, anchorsBySelect, activeAnchor]);
751
+ React.useEffect(() => {
752
+ return () => {
753
+ if (tooltipShowDelayTimerRef.current) {
754
+ clearTimeout(tooltipShowDelayTimerRef.current);
755
+ }
756
+ if (tooltipHideDelayTimerRef.current) {
757
+ clearTimeout(tooltipHideDelayTimerRef.current);
758
+ }
759
+ };
760
+ }, []);
761
+ React.useEffect(() => {
762
+ let selector = anchorSelect;
763
+ if (!selector && id) {
764
+ selector = `[data-tooltip-id='${id}']`;
765
+ }
766
+ if (!selector) {
767
+ return;
768
+ }
769
+ try {
770
+ const anchors = Array.from(document.querySelectorAll(selector));
771
+ setAnchorsBySelect(anchors);
772
+ }
773
+ catch (_a) {
774
+ // warning was already issued in the controller
775
+ setAnchorsBySelect([]);
776
+ }
777
+ }, [id, anchorSelect]);
778
+ const canShow = !hidden && content && show && Object.keys(inlineStyles).length > 0;
779
+ return rendered ? (React__default["default"].createElement(WrapperElement, { id: id, role: "tooltip", className: classNames__default["default"]('react-tooltip', coreStyles['tooltip'], styles[variant], className, `react-tooltip__place-${actualPlacement}`, {
780
+ [coreStyles['show']]: canShow,
781
+ [coreStyles['fixed']]: positionStrategy === 'fixed',
782
+ [coreStyles['clickable']]: clickable,
783
+ }), style: { ...externalStyles, ...inlineStyles }, ref: tooltipRef },
784
+ content,
785
+ React__default["default"].createElement(WrapperElement, { className: classNames__default["default"]('react-tooltip-arrow', coreStyles['arrow'], styles['arrow'], classNameArrow, {
786
+ /**
787
+ * changed from dash `no-arrow` to camelcase because of:
788
+ * https://github.com/indooorsman/esbuild-css-modules-plugin/issues/42
789
+ */
790
+ [coreStyles['noArrow']]: noArrow,
791
+ }), style: inlineArrowStyles, ref: tooltipArrowRef }))) : null;
792
+ };
793
+
794
+ /* eslint-disable react/no-danger */
795
+ const TooltipContent = ({ content }) => {
796
+ return React__default["default"].createElement("span", { dangerouslySetInnerHTML: { __html: content } });
797
+ };
798
+
799
+ 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, setIsOpen, afterShow, afterHide, }) => {
800
+ const [tooltipContent, setTooltipContent] = React.useState(content);
801
+ const [tooltipHtml, setTooltipHtml] = React.useState(html);
802
+ const [tooltipPlace, setTooltipPlace] = React.useState(place);
803
+ const [tooltipVariant, setTooltipVariant] = React.useState(variant);
804
+ const [tooltipOffset, setTooltipOffset] = React.useState(offset);
805
+ const [tooltipDelayShow, setTooltipDelayShow] = React.useState(delayShow);
806
+ const [tooltipDelayHide, setTooltipDelayHide] = React.useState(delayHide);
807
+ const [tooltipFloat, setTooltipFloat] = React.useState(float);
808
+ const [tooltipHidden, setTooltipHidden] = React.useState(hidden);
809
+ const [tooltipWrapper, setTooltipWrapper] = React.useState(wrapper);
810
+ const [tooltipEvents, setTooltipEvents] = React.useState(events);
811
+ const [tooltipPositionStrategy, setTooltipPositionStrategy] = React.useState(positionStrategy);
812
+ const [activeAnchor, setActiveAnchor] = React.useState(null);
813
+ /**
814
+ * @todo Remove this in a future version (provider/wrapper method is deprecated)
815
+ */
816
+ const { anchorRefs, activeAnchor: providerActiveAnchor } = useTooltip(id);
817
+ const getDataAttributesFromAnchorElement = (elementReference) => {
818
+ const dataAttributes = elementReference === null || elementReference === void 0 ? void 0 : elementReference.getAttributeNames().reduce((acc, name) => {
819
+ var _a;
820
+ if (name.startsWith('data-tooltip-')) {
821
+ const parsedAttribute = name.replace(/^data-tooltip-/, '');
822
+ acc[parsedAttribute] = (_a = elementReference === null || elementReference === void 0 ? void 0 : elementReference.getAttribute(name)) !== null && _a !== void 0 ? _a : null;
823
+ }
824
+ return acc;
825
+ }, {});
826
+ return dataAttributes;
827
+ };
828
+ const applyAllDataAttributesFromAnchorElement = (dataAttributes) => {
829
+ const handleDataAttributes = {
830
+ place: (value) => {
831
+ var _a;
832
+ setTooltipPlace((_a = value) !== null && _a !== void 0 ? _a : place);
833
+ },
834
+ content: (value) => {
835
+ setTooltipContent(value !== null && value !== void 0 ? value : content);
836
+ },
837
+ html: (value) => {
838
+ setTooltipHtml(value !== null && value !== void 0 ? value : html);
839
+ },
840
+ variant: (value) => {
841
+ var _a;
842
+ setTooltipVariant((_a = value) !== null && _a !== void 0 ? _a : variant);
843
+ },
844
+ offset: (value) => {
845
+ setTooltipOffset(value === null ? offset : Number(value));
846
+ },
847
+ wrapper: (value) => {
848
+ var _a;
849
+ setTooltipWrapper((_a = value) !== null && _a !== void 0 ? _a : wrapper);
850
+ },
851
+ events: (value) => {
852
+ const parsed = value === null || value === void 0 ? void 0 : value.split(' ');
853
+ setTooltipEvents(parsed !== null && parsed !== void 0 ? parsed : events);
854
+ },
855
+ 'position-strategy': (value) => {
856
+ var _a;
857
+ setTooltipPositionStrategy((_a = value) !== null && _a !== void 0 ? _a : positionStrategy);
858
+ },
859
+ 'delay-show': (value) => {
860
+ setTooltipDelayShow(value === null ? delayShow : Number(value));
861
+ },
862
+ 'delay-hide': (value) => {
863
+ setTooltipDelayHide(value === null ? delayHide : Number(value));
864
+ },
865
+ float: (value) => {
866
+ setTooltipFloat(value === null ? float : value === 'true');
867
+ },
868
+ hidden: (value) => {
869
+ setTooltipHidden(value === null ? hidden : value === 'true');
870
+ },
871
+ };
872
+ // reset unset data attributes to default values
873
+ // without this, data attributes from the last active anchor will still be used
874
+ Object.values(handleDataAttributes).forEach((handler) => handler(null));
875
+ Object.entries(dataAttributes).forEach(([key, value]) => {
876
+ var _a;
877
+ (_a = handleDataAttributes[key]) === null || _a === void 0 ? void 0 : _a.call(handleDataAttributes, value);
878
+ });
879
+ };
880
+ React.useEffect(() => {
881
+ setTooltipContent(content);
882
+ }, [content]);
883
+ React.useEffect(() => {
884
+ setTooltipHtml(html);
885
+ }, [html]);
886
+ React.useEffect(() => {
887
+ setTooltipPlace(place);
888
+ }, [place]);
889
+ React.useEffect(() => {
890
+ setTooltipVariant(variant);
891
+ }, [variant]);
892
+ React.useEffect(() => {
893
+ setTooltipOffset(offset);
894
+ }, [offset]);
895
+ React.useEffect(() => {
896
+ setTooltipDelayShow(delayShow);
897
+ }, [delayShow]);
898
+ React.useEffect(() => {
899
+ setTooltipDelayHide(delayHide);
900
+ }, [delayHide]);
901
+ React.useEffect(() => {
902
+ setTooltipFloat(float);
903
+ }, [float]);
904
+ React.useEffect(() => {
905
+ setTooltipHidden(hidden);
906
+ }, [hidden]);
907
+ React.useEffect(() => {
908
+ setTooltipPositionStrategy(positionStrategy);
909
+ }, [positionStrategy]);
910
+ React.useEffect(() => {
911
+ var _a;
912
+ const elementRefs = new Set(anchorRefs);
913
+ let selector = anchorSelect;
914
+ if (!selector && id) {
915
+ selector = `[data-tooltip-id='${id}']`;
916
+ }
917
+ if (selector) {
918
+ try {
919
+ const anchorsBySelect = document.querySelectorAll(selector);
920
+ anchorsBySelect.forEach((anchor) => {
921
+ elementRefs.add({ current: anchor });
922
+ });
923
+ }
924
+ catch (_b) {
925
+ {
926
+ // eslint-disable-next-line no-console
927
+ console.warn(`[react-tooltip] "${selector}" is not a valid CSS selector`);
928
+ }
929
+ }
930
+ }
931
+ const anchorById = document.querySelector(`[id='${anchorId}']`);
932
+ if (anchorById) {
933
+ elementRefs.add({ current: anchorById });
934
+ }
935
+ if (!elementRefs.size) {
936
+ return () => null;
937
+ }
938
+ const anchorElement = (_a = activeAnchor !== null && activeAnchor !== void 0 ? activeAnchor : anchorById) !== null && _a !== void 0 ? _a : providerActiveAnchor.current;
939
+ const observerCallback = (mutationList) => {
940
+ mutationList.forEach((mutation) => {
941
+ var _a;
942
+ if (!anchorElement ||
943
+ mutation.type !== 'attributes' ||
944
+ !((_a = mutation.attributeName) === null || _a === void 0 ? void 0 : _a.startsWith('data-tooltip-'))) {
945
+ return;
946
+ }
947
+ // make sure to get all set attributes, since all unset attributes are reset
948
+ const dataAttributes = getDataAttributesFromAnchorElement(anchorElement);
949
+ applyAllDataAttributesFromAnchorElement(dataAttributes);
950
+ });
951
+ };
952
+ // Create an observer instance linked to the callback function
953
+ const observer = new MutationObserver(observerCallback);
954
+ // do not check for subtree and childrens, we only want to know attribute changes
955
+ // to stay watching `data-attributes-*` from anchor element
956
+ const observerConfig = { attributes: true, childList: false, subtree: false };
957
+ if (anchorElement) {
958
+ const dataAttributes = getDataAttributesFromAnchorElement(anchorElement);
959
+ applyAllDataAttributesFromAnchorElement(dataAttributes);
960
+ // Start observing the target node for configured mutations
961
+ observer.observe(anchorElement, observerConfig);
962
+ }
963
+ return () => {
964
+ // Remove the observer when the tooltip is destroyed
965
+ observer.disconnect();
966
+ };
967
+ }, [anchorRefs, providerActiveAnchor, activeAnchor, anchorId, anchorSelect]);
968
+ /**
969
+ * content priority: children < render or content < html
970
+ * children should be lower priority so that it can be used as the "default" content
971
+ */
972
+ let renderedContent = children;
973
+ const contentWrapperRef = React.useRef(null);
974
+ if (render) {
975
+ const rendered = render({ content: tooltipContent !== null && tooltipContent !== void 0 ? tooltipContent : null, activeAnchor });
976
+ renderedContent = rendered ? (React__default["default"].createElement("div", { ref: contentWrapperRef, className: "react-tooltip-content-wrapper" }, rendered)) : null;
977
+ }
978
+ else if (tooltipContent) {
979
+ renderedContent = tooltipContent;
980
+ }
981
+ if (tooltipHtml) {
982
+ renderedContent = React__default["default"].createElement(TooltipContent, { content: tooltipHtml });
983
+ }
984
+ const props = {
985
+ id,
986
+ anchorId,
987
+ anchorSelect,
988
+ className,
989
+ classNameArrow,
990
+ content: renderedContent,
991
+ contentWrapperRef,
992
+ place: tooltipPlace,
993
+ variant: tooltipVariant,
994
+ offset: tooltipOffset,
995
+ wrapper: tooltipWrapper,
996
+ events: tooltipEvents,
997
+ openOnClick,
998
+ positionStrategy: tooltipPositionStrategy,
999
+ middlewares,
1000
+ delayShow: tooltipDelayShow,
1001
+ delayHide: tooltipDelayHide,
1002
+ float: tooltipFloat,
1003
+ hidden: tooltipHidden,
1004
+ noArrow,
1005
+ clickable,
1006
+ closeOnEsc,
1007
+ closeOnScroll,
1008
+ closeOnResize,
1009
+ style,
1010
+ position,
1011
+ isOpen,
1012
+ setIsOpen,
1013
+ afterShow,
1014
+ afterHide,
1015
+ activeAnchor,
1016
+ setActiveAnchor: (anchor) => setActiveAnchor(anchor),
1017
+ };
1018
+ return React__default["default"].createElement(Tooltip, { ...props });
1019
+ };
1020
+
1021
+ // those content will be replaced in build time with the `react-tooltip.css` builded content
1022
+ const TooltipCoreStyles = `:root {
1023
+ --rt-color-white: #fff;
1024
+ --rt-color-dark: #222;
1025
+ --rt-color-success: #8dc572;
1026
+ --rt-color-error: #be6464;
1027
+ --rt-color-warning: #f0ad4e;
1028
+ --rt-color-info: #337ab7;
1029
+ --rt-opacity: 0.9;
1030
+ }
1031
+
1032
+ .core-styles-module_tooltip__3vRRp {
1033
+ visibility: hidden;
1034
+ width: max-content;
1035
+ position: absolute;
1036
+ top: 0;
1037
+ left: 0;
1038
+ padding: 8px 16px;
1039
+ border-radius: 3px;
1040
+ font-size: 90%;
1041
+ pointer-events: none;
1042
+ opacity: 0;
1043
+ transition: opacity 0.3s ease-out;
1044
+ will-change: opacity, visibility;
1045
+ }
1046
+
1047
+ .core-styles-module_fixed__pcSol {
1048
+ position: fixed;
1049
+ }
1050
+
1051
+ .core-styles-module_arrow__cvMwQ {
1052
+ position: absolute;
1053
+ background: inherit;
1054
+ }
1055
+
1056
+ .core-styles-module_noArrow__xock6 {
1057
+ display: none;
1058
+ }
1059
+
1060
+ .core-styles-module_clickable__ZuTTB {
1061
+ pointer-events: auto;
1062
+ }
1063
+
1064
+ .core-styles-module_show__Nt9eE {
1065
+ visibility: visible;
1066
+ opacity: var(--rt-opacity);
1067
+ }
1068
+
1069
+ `;
1070
+ const TooltipStyles = `
1071
+
1072
+ .styles-module_arrow__K0L3T {
1073
+ width: 8px;
1074
+ height: 8px;
1075
+ transform: rotate(45deg);
1076
+ }
1077
+
1078
+ /** Types variant **/
1079
+ .styles-module_dark__xNqje {
1080
+ background: var(--rt-color-dark);
1081
+ color: var(--rt-color-white);
1082
+ }
1083
+
1084
+ .styles-module_light__Z6W-X {
1085
+ background-color: var(--rt-color-white);
1086
+ color: var(--rt-color-dark);
1087
+ }
1088
+
1089
+ .styles-module_success__A2AKt {
1090
+ background-color: var(--rt-color-success);
1091
+ color: var(--rt-color-white);
1092
+ }
1093
+
1094
+ .styles-module_warning__SCK0X {
1095
+ background-color: var(--rt-color-warning);
1096
+ color: var(--rt-color-white);
1097
+ }
1098
+
1099
+ .styles-module_error__JvumD {
1100
+ background-color: var(--rt-color-error);
1101
+ color: var(--rt-color-white);
1102
+ }
1103
+
1104
+ .styles-module_info__BWdHW {
1105
+ background-color: var(--rt-color-info);
1106
+ color: var(--rt-color-white);
1107
+ }
1108
+ `;
1109
+ injectStyle({ css: TooltipCoreStyles, type: 'core' });
1110
+ injectStyle({ css: TooltipStyles });
1111
+
1112
+ exports.Tooltip = TooltipController;
1113
+ exports.TooltipProvider = TooltipProvider;
1114
+ exports.TooltipWrapper = TooltipWrapper;
1115
+ exports.removeStyle = removeStyle;
1116
+
1117
+ Object.defineProperty(exports, '__esModule', { value: true });
1001
1118
 
1002
1119
  }));
1003
- //# sourceMappingURL=react-tooltip.umd.js.map