@udixio/ui-react 2.9.7 → 2.9.9
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.
- package/CHANGELOG.md +30 -0
- package/dist/index.cjs +3 -3
- package/dist/index.js +2158 -2042
- package/dist/lib/components/Tooltip.d.ts +9 -0
- package/dist/lib/components/Tooltip.d.ts.map +1 -0
- package/dist/lib/components/index.d.ts +1 -1
- package/dist/lib/effects/State.d.ts.map +1 -1
- package/dist/lib/hooks/index.d.ts +5 -0
- package/dist/lib/hooks/index.d.ts.map +1 -0
- package/dist/lib/hooks/useTooltipPosition.d.ts +22 -0
- package/dist/lib/hooks/useTooltipPosition.d.ts.map +1 -0
- package/dist/lib/hooks/useTooltipTrigger.d.ts +44 -0
- package/dist/lib/hooks/useTooltipTrigger.d.ts.map +1 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/interfaces/tooltip.interface.d.ts +24 -2
- package/dist/lib/interfaces/tooltip.interface.d.ts.map +1 -1
- package/dist/lib/styles/card.style.d.ts.map +1 -1
- package/dist/lib/styles/tooltip.style.d.ts +32 -4
- package/dist/lib/styles/tooltip.style.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/lib/components/Fab.tsx +2 -2
- package/src/lib/components/IconButton.tsx +3 -3
- package/src/lib/components/Tooltip.tsx +172 -0
- package/src/lib/components/index.ts +1 -1
- package/src/lib/effects/State.tsx +6 -2
- package/src/lib/hooks/index.ts +11 -0
- package/src/lib/hooks/useTooltipPosition.ts +95 -0
- package/src/lib/hooks/useTooltipTrigger.ts +270 -0
- package/src/lib/index.ts +1 -0
- package/src/lib/interfaces/tooltip.interface.ts +24 -2
- package/src/lib/styles/card.style.ts +4 -1
- package/src/lib/styles/tooltip.style.ts +1 -0
- package/src/stories/communication/tool-tip.stories.tsx +19 -19
- package/tsconfig.json +0 -6
- package/dist/lib/components/ToolTip.d.ts +0 -9
- package/dist/lib/components/ToolTip.d.ts.map +0 -1
- package/src/lib/components/ToolTip.tsx +0 -256
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
cloneElement,
|
|
3
|
-
isValidElement,
|
|
4
|
-
useEffect,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
} from 'react';
|
|
8
|
-
import { MotionProps } from '../utils';
|
|
9
|
-
import { Button } from './Button';
|
|
10
|
-
import { ToolTipInterface } from '../interfaces';
|
|
11
|
-
import { useToolTipStyle } from '../styles';
|
|
12
|
-
import { v4 } from 'uuid';
|
|
13
|
-
import { AnimatePresence, motion } from 'motion/react';
|
|
14
|
-
import { SyncedFixedWrapper } from '../effects';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Tooltips display brief labels or messages
|
|
18
|
-
* @status beta
|
|
19
|
-
* @category Communication
|
|
20
|
-
*/
|
|
21
|
-
export const ToolTip = ({
|
|
22
|
-
variant = 'plain',
|
|
23
|
-
buttons,
|
|
24
|
-
className,
|
|
25
|
-
children,
|
|
26
|
-
title,
|
|
27
|
-
text,
|
|
28
|
-
position,
|
|
29
|
-
targetRef,
|
|
30
|
-
ref,
|
|
31
|
-
trigger = ['hover', 'focus'],
|
|
32
|
-
transition,
|
|
33
|
-
...props
|
|
34
|
-
}: MotionProps<ToolTipInterface>) => {
|
|
35
|
-
transition = { duration: 0.3, delay: 0.4, ...transition };
|
|
36
|
-
|
|
37
|
-
if (!children && !targetRef) {
|
|
38
|
-
throw new Error('ToolTip must have a child or a targetRef');
|
|
39
|
-
}
|
|
40
|
-
if (!Array.isArray(trigger)) {
|
|
41
|
-
trigger = [trigger];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (buttons && !Array.isArray(buttons)) {
|
|
45
|
-
buttons = [buttons];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const internalRef = useRef<HTMLElement | null>(null); // Ref interne au cas où targetRef est undefined
|
|
49
|
-
const resolvedRef = targetRef || internalRef; // Utilise targetRef si défini, sinon internalRef
|
|
50
|
-
|
|
51
|
-
const [currentToolTipId, setCurrentToolTipId] = useState<string | null>(null);
|
|
52
|
-
const [id] = useState(v4());
|
|
53
|
-
const [isVisible, setIsVisible] = useState(false);
|
|
54
|
-
|
|
55
|
-
const timeout = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
56
|
-
const showTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
57
|
-
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
const handleUpdate = (event: CustomEvent) => {
|
|
60
|
-
setCurrentToolTipId(event.detail);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
document.addEventListener('tooltip-update', handleUpdate as EventListener);
|
|
64
|
-
return () => {
|
|
65
|
-
document.removeEventListener(
|
|
66
|
-
'tooltip-update',
|
|
67
|
-
handleUpdate as EventListener,
|
|
68
|
-
);
|
|
69
|
-
};
|
|
70
|
-
}, []);
|
|
71
|
-
|
|
72
|
-
useEffect(() => {
|
|
73
|
-
if (timeout.current) clearTimeout(timeout.current);
|
|
74
|
-
if (showTimeout.current) clearTimeout(showTimeout.current);
|
|
75
|
-
|
|
76
|
-
if (currentToolTipId) {
|
|
77
|
-
if (currentToolTipId === id) {
|
|
78
|
-
showTimeout.current = setTimeout(
|
|
79
|
-
() => {
|
|
80
|
-
setIsVisible(true);
|
|
81
|
-
},
|
|
82
|
-
(transition?.delay ?? 0) * 1000,
|
|
83
|
-
);
|
|
84
|
-
} else {
|
|
85
|
-
setIsVisible(false);
|
|
86
|
-
}
|
|
87
|
-
} else {
|
|
88
|
-
timeout.current = setTimeout(() => {
|
|
89
|
-
setIsVisible(false);
|
|
90
|
-
}, 1200);
|
|
91
|
-
}
|
|
92
|
-
}, [currentToolTipId, id]);
|
|
93
|
-
|
|
94
|
-
// Ajouter des gestionnaires sur l'élément cible (targetRef ou internalRef)
|
|
95
|
-
|
|
96
|
-
const handleMouseEnter = () => {
|
|
97
|
-
if (trigger.includes('hover')) {
|
|
98
|
-
const event = new CustomEvent('tooltip-update', { detail: id });
|
|
99
|
-
document.dispatchEvent(event);
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const handleMouseLeave = () => {
|
|
104
|
-
if (trigger.includes('hover')) {
|
|
105
|
-
const event = new CustomEvent('tooltip-update', { detail: null });
|
|
106
|
-
document.dispatchEvent(event);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const handleClick = () => {
|
|
111
|
-
if (trigger.includes('click')) {
|
|
112
|
-
const event = new CustomEvent('tooltip-update', {
|
|
113
|
-
detail: isVisible ? null : id,
|
|
114
|
-
});
|
|
115
|
-
document.dispatchEvent(event);
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const handleFocus = () => {
|
|
120
|
-
if (trigger.includes('focus')) {
|
|
121
|
-
const event = new CustomEvent('tooltip-update', { detail: id });
|
|
122
|
-
document.dispatchEvent(event);
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const handleBlur = () => {
|
|
127
|
-
if (trigger.includes('focus')) {
|
|
128
|
-
const event = new CustomEvent('tooltip-update', { detail: null });
|
|
129
|
-
document.dispatchEvent(event);
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
useEffect(() => {
|
|
134
|
-
if (resolvedRef?.current) {
|
|
135
|
-
const targetElement = resolvedRef.current;
|
|
136
|
-
|
|
137
|
-
targetElement.addEventListener('mouseenter', handleMouseEnter);
|
|
138
|
-
targetElement.addEventListener('mouseleave', handleMouseLeave);
|
|
139
|
-
targetElement.addEventListener('click', handleClick);
|
|
140
|
-
targetElement.addEventListener('focus', handleFocus);
|
|
141
|
-
targetElement.addEventListener('blur', handleBlur);
|
|
142
|
-
|
|
143
|
-
// Nettoyage au démontage
|
|
144
|
-
return () => {
|
|
145
|
-
targetElement.removeEventListener('mouseenter', handleMouseEnter);
|
|
146
|
-
targetElement.removeEventListener('mouseleave', handleMouseLeave);
|
|
147
|
-
targetElement.removeEventListener('click', handleClick);
|
|
148
|
-
targetElement.removeEventListener('focus', handleFocus);
|
|
149
|
-
targetElement.removeEventListener('blur', handleBlur);
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
return;
|
|
153
|
-
}, [resolvedRef, trigger, id, isVisible]);
|
|
154
|
-
|
|
155
|
-
// Si targetRef est undefined, on applique la réf au premier enfant
|
|
156
|
-
const enhancedChildren =
|
|
157
|
-
!targetRef && isValidElement(children)
|
|
158
|
-
? cloneElement(children, { ref: internalRef } as any)
|
|
159
|
-
: children;
|
|
160
|
-
|
|
161
|
-
if (!position && typeof window !== 'undefined') {
|
|
162
|
-
if (resolvedRef?.current && !position) {
|
|
163
|
-
const rect = resolvedRef.current.getBoundingClientRect();
|
|
164
|
-
|
|
165
|
-
const viewportWidth = window.innerWidth;
|
|
166
|
-
const viewportHeight = window.innerHeight;
|
|
167
|
-
|
|
168
|
-
const x = rect.left / viewportWidth; // X entre 0 et 1
|
|
169
|
-
const y = rect.top / viewportHeight; // Y entre 0 et 1
|
|
170
|
-
|
|
171
|
-
if (variant === 'plain') {
|
|
172
|
-
if (x < 1 / 3) {
|
|
173
|
-
position = 'right';
|
|
174
|
-
} else if (x > 2 / 3) {
|
|
175
|
-
position = 'left';
|
|
176
|
-
} else {
|
|
177
|
-
position = y > 0.5 ? 'top' : 'bottom';
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
if (x < 1 / 2 && y < 1 / 2) {
|
|
181
|
-
position = 'bottom-right';
|
|
182
|
-
} else if (x > 1 / 2 && y < 1 / 2) {
|
|
183
|
-
position = 'bottom-left';
|
|
184
|
-
} else if (x > 1 / 2 && y > 1 / 2) {
|
|
185
|
-
position = 'top-left';
|
|
186
|
-
} else if (x < 1 / 2 && y > 1 / 2) {
|
|
187
|
-
position = 'top-right';
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const styles = useToolTipStyle({
|
|
194
|
-
variant,
|
|
195
|
-
buttons,
|
|
196
|
-
className,
|
|
197
|
-
title,
|
|
198
|
-
text,
|
|
199
|
-
position,
|
|
200
|
-
trigger,
|
|
201
|
-
targetRef: targetRef as any,
|
|
202
|
-
children: children as any,
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
const variants = {
|
|
206
|
-
open: {
|
|
207
|
-
opacity: 1,
|
|
208
|
-
height: 'auto',
|
|
209
|
-
},
|
|
210
|
-
close: {
|
|
211
|
-
opacity: 0,
|
|
212
|
-
height: 16,
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
return (
|
|
217
|
-
<>
|
|
218
|
-
{enhancedChildren}
|
|
219
|
-
<AnimatePresence>
|
|
220
|
-
{isVisible && (
|
|
221
|
-
<SyncedFixedWrapper targetRef={resolvedRef}>
|
|
222
|
-
<motion.div
|
|
223
|
-
initial={'close'}
|
|
224
|
-
variants={variants}
|
|
225
|
-
animate={'open'}
|
|
226
|
-
transition={{ duration: transition.duration }}
|
|
227
|
-
exit={'close'}
|
|
228
|
-
className={styles.toolTip}
|
|
229
|
-
{...props}
|
|
230
|
-
onMouseEnter={handleMouseEnter}
|
|
231
|
-
onMouseLeave={handleMouseLeave}
|
|
232
|
-
>
|
|
233
|
-
<div className={styles.container}>
|
|
234
|
-
{title && <div className={styles.subHead}>{title}</div>}
|
|
235
|
-
<div className={styles.supportingText}>{text}</div>
|
|
236
|
-
{buttons && (
|
|
237
|
-
<div className={styles.actions}>
|
|
238
|
-
{Array.isArray(buttons) &&
|
|
239
|
-
buttons.map((buttonArgs, index) => (
|
|
240
|
-
<Button
|
|
241
|
-
key={index}
|
|
242
|
-
size={'small'}
|
|
243
|
-
variant={'text'}
|
|
244
|
-
{...buttonArgs}
|
|
245
|
-
/>
|
|
246
|
-
))}
|
|
247
|
-
</div>
|
|
248
|
-
)}
|
|
249
|
-
</div>
|
|
250
|
-
</motion.div>
|
|
251
|
-
</SyncedFixedWrapper>
|
|
252
|
-
)}
|
|
253
|
-
</AnimatePresence>
|
|
254
|
-
</>
|
|
255
|
-
);
|
|
256
|
-
};
|