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