funda-ui 4.7.515 → 4.7.525

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,3 +1,5 @@
1
+
2
+
1
3
  /* ======================================================
2
4
  <!-- Tooltip -->
3
5
  /* ====================================================== */
@@ -16,22 +18,22 @@
16
18
  * 10. Size
17
19
  */
18
20
 
19
- .tooltip__wrapper {
20
-
21
- --tooltip-box-shadow: 0 5px 15px 0 rgba(0,0,0,.07), 0 15px 35px 0 rgba(50,50,93,.1);
22
- --tooltip-content-bg: rgba(17, 17, 17, 0.9);
23
- --tooltip-content-color: #fff;
24
- --tooltip-content-font-size: 0.75em;
25
- --tooltip-content-padding-x: 1em;
26
- --tooltip-content-padding-y: .5em;
27
- --tooltip-content-line-height: 1.5;
28
- --tooltip-arrow-bg-top: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%280%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
29
- --tooltip-arrow-bg-bottom: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28180%2018%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
30
- --tooltip-arrow-bg-left: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28-90%2018%2018%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
31
- --tooltip-arrow-bg-right: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%2890%206%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
32
-
33
- --tooltip-arrow-width: 18px;
34
- --tooltip-arrow-height: 6px;
21
+ .cus-tooltip__wrapper {
22
+
23
+ --cus-tooltip-box-shadow: 0 5px 15px 0 rgba(0,0,0,.07), 0 15px 35px 0 rgba(50,50,93,.1);
24
+ --cus-tooltip-content-bg: rgba(17, 17, 17, 0.9);
25
+ --cus-tooltip-content-color: #fff;
26
+ --cus-tooltip-content-font-size: 0.75em;
27
+ --cus-tooltip-content-padding-x: 1em;
28
+ --cus-tooltip-content-padding-y: .5em;
29
+ --cus-tooltip-content-line-height: 1.5;
30
+ --cus-tooltip-arrow-bg-top: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%280%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
31
+ --cus-tooltip-arrow-bg-bottom: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28180%2018%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
32
+ --cus-tooltip-arrow-bg-left: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28-90%2018%2018%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
33
+ --cus-tooltip-arrow-bg-right: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%2890%206%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
34
+
35
+ --cus-tooltip-arrow-width: 18px;
36
+ --cus-tooltip-arrow-height: 6px;
35
37
 
36
38
 
37
39
  position: absolute;
@@ -50,7 +52,7 @@
50
52
  display: block !important;
51
53
 
52
54
  &::before,
53
- > .tooltip__content {
55
+ > .cus-tooltip__content {
54
56
  opacity: 1;
55
57
  }
56
58
  }
@@ -58,21 +60,21 @@
58
60
  &:focus {
59
61
 
60
62
  &::before,
61
- > .tooltip__content {
63
+ > .cus-tooltip__content {
62
64
  opacity: 1;
63
65
  }
64
66
  }
65
67
 
66
68
 
67
69
  &::before,
68
- > .tooltip__content {
70
+ > .cus-tooltip__content {
69
71
  backface-visibility: hidden;
70
72
  will-change: transform;
71
73
  opacity: 0;
72
74
  box-sizing: border-box;
73
75
  z-index: 10;
74
76
  transform-origin: top;
75
- box-shadow: var(--tooltip-box-shadow);
77
+ box-shadow: var(--cus-tooltip-box-shadow);
76
78
  transition: none !important; /* Don't use transition if position is outside window */
77
79
  }
78
80
 
@@ -84,18 +86,19 @@
84
86
  ---------------------------
85
87
  */
86
88
 
87
- > .tooltip__content {
88
- background: var(--tooltip-content-bg);
89
+ > .cus-tooltip__content {
90
+ pointer-events: auto;
91
+ background: var(--cus-tooltip-content-bg);
89
92
  border-radius: 4px;
90
- color: var(--tooltip-content-color);
93
+ color: var(--cus-tooltip-content-color);
91
94
  content: attr(aria-label);
92
- font-size: var(--tooltip-content-font-size);
95
+ font-size: var(--cus-tooltip-content-font-size);
93
96
  font-weight: normal;
94
97
  text-transform: none;
95
- padding: var(--tooltip-content-padding-y) var(--tooltip-content-padding-x);
98
+ padding: var(--cus-tooltip-content-padding-y) var(--cus-tooltip-content-padding-x);
96
99
  white-space: nowrap;
97
100
  box-sizing: content-box;
98
- line-height: var(--tooltip-content-line-height);
101
+ line-height: var(--cus-tooltip-content-line-height);
99
102
 
100
103
 
101
104
  img {
@@ -115,22 +118,22 @@
115
118
 
116
119
  &[data-microtip-position|="top"] {
117
120
  &::before {
118
- background: var(--tooltip-arrow-bg-top);
119
- height: var(--tooltip-arrow-height);
120
- width: var(--tooltip-arrow-width);
121
+ background: var(--cus-tooltip-arrow-bg-top);
122
+ height: var(--cus-tooltip-arrow-height);
123
+ width: var(--cus-tooltip-arrow-width);
121
124
  }
122
125
 
123
- > .tooltip__content {
124
- margin-bottom: var(--tooltip-arrow-height);
126
+ > .cus-tooltip__content {
127
+ margin-bottom: var(--cus-tooltip-arrow-height);
125
128
  }
126
129
 
127
130
  &::before {
128
- top: calc(100% - var(--tooltip-arrow-height));
129
- left: calc(var(--tooltip-arrow-width)/2 * -1);
131
+ top: calc(100% - var(--cus-tooltip-arrow-height));
132
+ left: calc(var(--cus-tooltip-arrow-width)/2 * -1);
130
133
  }
131
134
 
132
- > .tooltip__content {
133
- bottom: calc(100% + var(--tooltip-arrow-height));
135
+ > .cus-tooltip__content {
136
+ bottom: calc(100% + var(--cus-tooltip-arrow-height));
134
137
  left: 50%;
135
138
  transform: translateX(-50%);
136
139
  }
@@ -144,10 +147,10 @@
144
147
  */
145
148
 
146
149
  &[data-microtip-position="top-left"] {
147
- > .tooltip__content {
148
- bottom: calc(100% + var(--tooltip-arrow-height));
150
+ > .cus-tooltip__content {
151
+ bottom: calc(100% + var(--cus-tooltip-arrow-height));
149
152
  left: 50%;
150
- transform: translateX(calc(-100% + var(--tooltip-arrow-width)));
153
+ transform: translateX(calc(-100% + var(--cus-tooltip-arrow-width)));
151
154
  }
152
155
 
153
156
  }
@@ -161,10 +164,10 @@
161
164
  */
162
165
 
163
166
  &[data-microtip-position="top-right"] {
164
- > .tooltip__content {
165
- bottom: calc(100% + var(--tooltip-arrow-height));
167
+ > .cus-tooltip__content {
168
+ bottom: calc(100% + var(--cus-tooltip-arrow-height));
166
169
  left: 50%;
167
- transform: translateX(calc(0% - var(--tooltip-arrow-width)));
170
+ transform: translateX(calc(0% - var(--cus-tooltip-arrow-width)));
168
171
  }
169
172
  }
170
173
 
@@ -177,25 +180,25 @@
177
180
 
178
181
  &[data-microtip-position|="bottom"] {
179
182
  &::before {
180
- background: var(--tooltip-arrow-bg-bottom);
181
- height: var(--tooltip-arrow-height);
182
- width: var(--tooltip-arrow-width);
183
+ background: var(--cus-tooltip-arrow-bg-bottom);
184
+ height: var(--cus-tooltip-arrow-height);
185
+ width: var(--cus-tooltip-arrow-width);
183
186
  margin-top: 5px;
184
187
  margin-bottom: 0;
185
188
  }
186
189
 
187
- > .tooltip__content {
188
- margin-top: var(--tooltip-arrow-height);
190
+ > .cus-tooltip__content {
191
+ margin-top: var(--cus-tooltip-arrow-height);
189
192
  }
190
193
 
191
194
  &::before {
192
- bottom: calc(100% - var(--tooltip-arrow-height));
193
- left: calc(var(--tooltip-arrow-width)/2 * -1);
195
+ bottom: calc(100% - var(--cus-tooltip-arrow-height));
196
+ left: calc(var(--cus-tooltip-arrow-width)/2 * -1);
194
197
  }
195
198
 
196
- > .tooltip__content {
199
+ > .cus-tooltip__content {
197
200
  bottom: auto;
198
- top: calc(100% + var(--tooltip-arrow-height));
201
+ top: calc(100% + var(--cus-tooltip-arrow-height));
199
202
  left: 50%;
200
203
  transform: translateX(-50%);
201
204
  }
@@ -210,11 +213,11 @@
210
213
 
211
214
 
212
215
  &[data-microtip-position="bottom-left"] {
213
- > .tooltip__content {
216
+ > .cus-tooltip__content {
214
217
  bottom: auto;
215
- top: calc(100% + var(--tooltip-arrow-height));
218
+ top: calc(100% + var(--cus-tooltip-arrow-height));
216
219
  left: 50%;
217
- transform: translateX(calc(-100% + var(--tooltip-arrow-width)));
220
+ transform: translateX(calc(-100% + var(--cus-tooltip-arrow-width)));
218
221
  }
219
222
  }
220
223
 
@@ -226,11 +229,11 @@
226
229
 
227
230
 
228
231
  &[data-microtip-position="bottom-right"] {
229
- > .tooltip__content {
232
+ > .cus-tooltip__content {
230
233
  bottom: auto;
231
- top: calc(100% + var(--tooltip-arrow-height));
234
+ top: calc(100% + var(--cus-tooltip-arrow-height));
232
235
  left: 50%;
233
- transform: translateX(calc(0% - var(--tooltip-arrow-width)));
236
+ transform: translateX(calc(0% - var(--cus-tooltip-arrow-width)));
234
237
  }
235
238
  }
236
239
 
@@ -242,7 +245,7 @@
242
245
  10. Size
243
246
  ---------------------------
244
247
  */
245
- &[data-microtip-size="auto"].tooltip__content {
248
+ &[data-microtip-size="auto"].cus-tooltip__content {
246
249
  white-space: nowrap;
247
250
  width: auto;
248
251
  max-width: 530px;
@@ -250,17 +253,17 @@
250
253
  text-overflow: ellipsis;
251
254
  }
252
255
 
253
- &[data-microtip-size="small"].tooltip__content {
256
+ &[data-microtip-size="small"].cus-tooltip__content {
254
257
  white-space: initial;
255
258
  width: 80px;
256
259
  }
257
260
 
258
- &[data-microtip-size="medium"].tooltip__content {
261
+ &[data-microtip-size="medium"].cus-tooltip__content {
259
262
  white-space: initial;
260
263
  width: 150px;
261
264
  }
262
265
 
263
- &[data-microtip-size="large"].tooltip__content {
266
+ &[data-microtip-size="large"].cus-tooltip__content {
264
267
  white-space: initial;
265
268
  width: 260px;
266
269
  }
@@ -1,4 +1,4 @@
1
- import React, { useState, useRef, useEffect } from 'react';
1
+ import React, { useState, useRef, useEffect, useImperativeHandle, forwardRef, useMemo } from 'react';
2
2
 
3
3
  import RootPortal from 'funda-root-portal';
4
4
 
@@ -12,7 +12,6 @@ import { getElCSS } from 'funda-utils/dist/cjs/inputsCalculation';
12
12
 
13
13
 
14
14
 
15
-
16
15
  export type TooltipProps = {
17
16
  triggerClassName?: string;
18
17
  wrapperClassName?: string;
@@ -30,40 +29,27 @@ export type TooltipProps = {
30
29
  mouseOutDelay?: number;
31
30
  /** Set a piece of text or HTML code */
32
31
  content?: React.ReactNode;
32
+ /** If true, Tooltip is controlled by parent via ref, not by mouse events */
33
+ controlled?: boolean;
34
+ /** Custom color for the popup arrow */
35
+ popupArrowColor?: number[];
36
+ /** Custom style for the popup content */
37
+ popupContentStyle?: React.CSSProperties;
38
+ /** If true, tooltip closes only if mouse does not enter wrapper within timeout after leaving trigger */
39
+ delayedClose?: boolean;
40
+ /** Timeout in ms for delayed close (ms) */
41
+ delayedCloseTimeout?: number;
42
+ /** Called when mouse enters the tooltip wrapper */
43
+ onContentMouseEnter?: (event: React.MouseEvent<HTMLDivElement>) => void;
44
+ /** Called when mouse leaves the tooltip wrapper */
45
+ onContentMouseLeave?: (event: React.MouseEvent<HTMLDivElement>) => void;
33
46
  /** -- */
34
47
  id?: string;
35
48
  children: React.ReactNode;
36
49
  };
37
50
 
38
- const useContainerDimensions = (myRef: any) => {
39
- const [dimensions, setDimensions] = useState({ width: 0, height: 0 })
40
-
41
- useEffect(() => {
42
- const getDimensions = () => ({
43
- width: myRef.current.offsetWidth,
44
- height: myRef.current.offsetHeight
45
- })
46
-
47
- const handleResize = () => {
48
- setDimensions(getDimensions())
49
- }
50
-
51
- if (myRef.current) {
52
- setDimensions(getDimensions())
53
- }
54
-
55
- window.addEventListener("resize", handleResize)
56
-
57
- return () => {
58
- window.removeEventListener("resize", handleResize)
59
- }
60
- }, [myRef])
61
-
62
- return dimensions;
63
- };
64
-
65
-
66
- const Tooltip = (props: TooltipProps) => {
51
+ // Use forwardRef to expose imperative methods
52
+ const Tooltip = forwardRef<any, TooltipProps>((props, ref) => {
67
53
  const {
68
54
  triggerClassName,
69
55
  wrapperClassName,
@@ -75,7 +61,14 @@ const Tooltip = (props: TooltipProps) => {
75
61
  mouseOutDelay,
76
62
  content,
77
63
  id,
78
- children
64
+ children,
65
+ controlled,
66
+ popupArrowColor,
67
+ popupContentStyle,
68
+ delayedClose,
69
+ delayedCloseTimeout,
70
+ onContentMouseEnter,
71
+ onContentMouseLeave
79
72
  } = props;
80
73
 
81
74
 
@@ -95,12 +88,62 @@ const Tooltip = (props: TooltipProps) => {
95
88
  y: 0
96
89
  });
97
90
 
91
+ const popupArrowStyle = useMemo(() => {
92
+ if (
93
+ typeof popupArrowColor !== 'undefined' &&
94
+ Array.isArray(popupArrowColor) &&
95
+ popupArrowColor.length === 4
96
+ ) {
97
+ return {
98
+ '--cus-tooltip-arrow-bg-top': `url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%28${popupArrowColor[0]},%20${popupArrowColor[1]},%20${popupArrowColor[2]},%20${popupArrowColor[3]}%29%22%20transform%3D%22rotate%280%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat`,
99
+ '--cus-tooltip-arrow-bg-bottom': `url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%28${popupArrowColor[0]},%20${popupArrowColor[1]},%20${popupArrowColor[2]},%20${popupArrowColor[3]}%29%22%20transform%3D%22rotate%28180%2018%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat`,
100
+ '--cus-tooltip-arrow-bg-left': `url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%28${popupArrowColor[0]},%20${popupArrowColor[1]},%20${popupArrowColor[2]},%20${popupArrowColor[3]}%29%22%20transform%3D%22rotate%28-90%2018%2018%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat`,
101
+ '--cus-tooltip-arrow-bg-right': `url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%28${popupArrowColor[0]},%20${popupArrowColor[1]},%20${popupArrowColor[2]},%20${popupArrowColor[3]}%29%22%20transform%3D%22rotate%2890%206%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat`,
102
+ };
103
+ }
104
+ return undefined;
105
+ }, [popupArrowColor]);
106
+
107
+ // Expose show/hide methods to parent via ref
108
+ useImperativeHandle(ref, () => ({
109
+ show: () => {
110
+ // Find the trigger element
111
+ const triggerEl = rootRef.current;
112
+ if (triggerEl) {
113
+ // Calculate position (copy from handleMouseEnter)
114
+ const { x, y, width, height } = getAbsolutePositionOfStage(triggerEl);
115
+ let pos = triggerEl.dataset.microtipPosition;
116
+ if (typeof pos === 'undefined') pos = 'top';
117
+
118
+ if (pos.indexOf('top') >= 0) {
119
+ setPosition({
120
+ x: x + (width / 2) + 'px',
121
+ y: y - height - POS_OFFSET + 'px'
122
+ });
123
+ }
124
+ if (pos.indexOf('bottom') >= 0) {
125
+ setPosition({
126
+ x: x + (width / 2) + 'px',
127
+ y: y + height + POS_OFFSET + 'px'
128
+ });
129
+ }
130
+ }
131
+ setIsShow(true);
132
+ },
133
+ hide: () => {
134
+ hideTip();
135
+ }
136
+ }), [POS_OFFSET]);
98
137
 
99
138
 
100
139
  // click outside
101
140
  useClickOutside({
102
- enabled: isShow && rootRef.current,
141
+ enabled: isShow && rootRef.current && !controlled, // Only auto-close if not controlled
103
142
  isOutside: (event: any) => {
143
+ // Prevent closing when clicking inside the tooltip wrapper
144
+ if (modalRef.current && modalRef.current.contains(event.target)) {
145
+ return false; // Click is inside the tooltip wrapper, do not close
146
+ }
104
147
  // close dropdown when other dropdown is opened
105
148
  return (
106
149
  (rootRef.current !== event.target && !rootRef.current.contains(event.target as HTMLElement))
@@ -109,7 +152,7 @@ const Tooltip = (props: TooltipProps) => {
109
152
  handle: (event: any) => {
110
153
  hideTip();
111
154
  }
112
- }, [isShow, rootRef]);
155
+ }, [isShow, rootRef, controlled]);
113
156
 
114
157
 
115
158
 
@@ -153,7 +196,7 @@ const Tooltip = (props: TooltipProps) => {
153
196
  const _modalRef: any = modalRef.current;
154
197
  if (_modalRef === null) return;
155
198
 
156
- const _modalContent = _modalRef.querySelector('.tooltip__content');
199
+ const _modalContent = _modalRef.querySelector('.cus-tooltip__content');
157
200
  const _modalBox = _modalContent.getBoundingClientRect();
158
201
  if (typeof _modalContent.dataset.offset === 'undefined' && _modalBox.left > 0) {
159
202
 
@@ -197,6 +240,7 @@ const Tooltip = (props: TooltipProps) => {
197
240
  };
198
241
 
199
242
  function handleMouseEnter(e: any) {
243
+ if (controlled) return; // Do nothing if controlled
200
244
  stopTimerHover();
201
245
  stopTimerMouseout();
202
246
  startTimerHover();
@@ -239,6 +283,7 @@ const Tooltip = (props: TooltipProps) => {
239
283
 
240
284
 
241
285
  function handleMouseLeave() {
286
+ if (controlled) return; // Do nothing if controlled
242
287
  stopTimerHover();
243
288
  stopTimerMouseout();
244
289
  startTimerMouseout();
@@ -250,10 +295,60 @@ const Tooltip = (props: TooltipProps) => {
250
295
  }
251
296
 
252
297
 
298
+ // Timer for delayed close
299
+ const delayedCloseTimerRef = useRef<any>(null);
300
+ const DELAYED_CLOSE_TIMEOUT = typeof delayedCloseTimeout === 'number' ? delayedCloseTimeout : 1500;
301
+
302
+ // Handler for mouse leave on trigger (when delayedClose is enabled)
303
+ function handleTriggerMouseLeave() {
304
+ if (controlled) return;
305
+ if (delayedClose) {
306
+ // Start delayed close timer
307
+ if (delayedCloseTimerRef.current) clearTimeout(delayedCloseTimerRef.current);
308
+ delayedCloseTimerRef.current = setTimeout(() => {
309
+ hideTip();
310
+ }, DELAYED_CLOSE_TIMEOUT);
311
+ } else {
312
+ stopTimerHover();
313
+ stopTimerMouseout();
314
+ startTimerMouseout();
315
+ }
316
+ }
317
+
318
+ // Handler for mouse enter on wrapper (cancel delayed close)
319
+ function handleWrapperMouseEnter(event?: React.MouseEvent<HTMLDivElement>) {
320
+ if (controlled) return;
321
+ if (delayedClose && delayedCloseTimerRef.current) {
322
+ clearTimeout(delayedCloseTimerRef.current);
323
+ delayedCloseTimerRef.current = null;
324
+ }
325
+ // Call user-provided handler if present
326
+ if (onContentMouseEnter && event) {
327
+ onContentMouseEnter(event);
328
+ }
329
+ }
330
+
331
+ // Handler for mouse leave on wrapper (restart delayed close timer)
332
+ function handleWrapperMouseLeave(event?: React.MouseEvent<HTMLDivElement>) {
333
+ if (controlled) return;
334
+ if (delayedClose) {
335
+ if (delayedCloseTimerRef.current) clearTimeout(delayedCloseTimerRef.current);
336
+ delayedCloseTimerRef.current = setTimeout(() => {
337
+ hideTip();
338
+ }, DELAYED_CLOSE_TIMEOUT);
339
+ }
340
+ // Call user-provided handler if present
341
+ if (onContentMouseLeave && event) {
342
+ onContentMouseLeave(event);
343
+ }
344
+ }
345
+
346
+
253
347
  useEffect(() => {
254
348
  return () => {
255
349
  stopTimerHover();
256
350
  stopTimerMouseout();
351
+ if (delayedCloseTimerRef.current) clearTimeout(delayedCloseTimerRef.current);
257
352
  };
258
353
  }, []);
259
354
 
@@ -268,15 +363,15 @@ const Tooltip = (props: TooltipProps) => {
268
363
 
269
364
  <div
270
365
  ref={rootRef}
271
- data-overlay-id={`tooltip__wrapper-${idRes}`}
366
+ data-overlay-id={`cus-tooltip__wrapper-${idRes}`}
272
367
  className={combinedCls(
273
- 'tooltip__trigger',
368
+ 'cus-tooltip__trigger',
274
369
  clsWrite(triggerClassName, 'd-inline-block')
275
370
  )}
276
371
  data-microtip-position={direction || 'top'}
277
372
  data-microtip-size={size || 'auto'}
278
373
  onMouseEnter={handleMouseEnter}
279
- onMouseLeave={handleMouseLeave}
374
+ onMouseLeave={delayedClose ? handleTriggerMouseLeave : handleMouseLeave}
280
375
  >
281
376
  {children}
282
377
  </div>
@@ -285,9 +380,9 @@ const Tooltip = (props: TooltipProps) => {
285
380
  <RootPortal show={isShow} containerClassName="Tooltip">
286
381
  <div
287
382
  ref={modalRef}
288
- id={`tooltip__wrapper-${idRes}`}
383
+ id={`cus-tooltip__wrapper-${idRes}`}
289
384
  className={combinedCls(
290
- 'tooltip__wrapper',
385
+ 'cus-tooltip__wrapper',
291
386
  wrapperClassName,
292
387
  'active'
293
388
  )}
@@ -297,10 +392,15 @@ const Tooltip = (props: TooltipProps) => {
297
392
  style={{
298
393
  left: position.x,
299
394
  top: position.y,
300
- display: 'none'
395
+ display: 'none',
396
+ ...popupArrowStyle
301
397
  }}
398
+ onMouseEnter={delayedClose || onContentMouseEnter ? (e) => handleWrapperMouseEnter(e) : undefined}
399
+ onMouseLeave={delayedClose || onContentMouseLeave ? (e) => handleWrapperMouseLeave(e) : undefined}
302
400
  >
303
- <div className="tooltip__content">{content}</div>
401
+ <div className="cus-tooltip__content" style={{
402
+ ...popupContentStyle
403
+ }}>{content}</div>
304
404
  </div>
305
405
 
306
406
  </RootPortal>
@@ -311,7 +411,6 @@ const Tooltip = (props: TooltipProps) => {
311
411
 
312
412
  </>
313
413
  )
314
- };
315
-
414
+ });
316
415
 
317
416
  export default Tooltip;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "UIUX Lab",
3
3
  "email": "uiuxlab@gmail.com",
4
4
  "name": "funda-ui",
5
- "version": "4.7.515",
5
+ "version": "4.7.525",
6
6
  "description": "React components using pure Bootstrap 5+ which does not contain any external style and script libraries.",
7
7
  "repository": {
8
8
  "type": "git",