@cleartrip/ct-design-tooltip 4.0.0 → 5.0.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.
Files changed (63) hide show
  1. package/README.md +97 -0
  2. package/dist/Tooltip.d.ts +2 -5
  3. package/dist/Tooltip.d.ts.map +1 -1
  4. package/dist/Tooltip.native.d.ts +11 -0
  5. package/dist/Tooltip.native.d.ts.map +1 -0
  6. package/dist/TooltipArrow.d.ts +10 -0
  7. package/dist/TooltipArrow.d.ts.map +1 -0
  8. package/dist/TooltipContainer.d.ts +14 -0
  9. package/dist/TooltipContainer.d.ts.map +1 -0
  10. package/dist/constants.d.ts +19 -0
  11. package/dist/constants.d.ts.map +1 -0
  12. package/dist/ct-design-tooltip.browser.cjs.js +1 -1
  13. package/dist/ct-design-tooltip.browser.cjs.js.map +1 -1
  14. package/dist/ct-design-tooltip.browser.esm.js +1 -1
  15. package/dist/ct-design-tooltip.browser.esm.js.map +1 -1
  16. package/dist/ct-design-tooltip.cjs.js +377 -116
  17. package/dist/ct-design-tooltip.cjs.js.map +1 -1
  18. package/dist/ct-design-tooltip.esm.js +377 -112
  19. package/dist/ct-design-tooltip.esm.js.map +1 -1
  20. package/dist/ct-design-tooltip.umd.js +2020 -149
  21. package/dist/ct-design-tooltip.umd.js.map +1 -1
  22. package/dist/index.d.ts +2 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/style.d.ts +112 -13
  25. package/dist/style.d.ts.map +1 -1
  26. package/dist/type.d.ts +42 -19
  27. package/dist/type.d.ts.map +1 -1
  28. package/dist/webStyle.d.ts +170 -0
  29. package/dist/webStyle.d.ts.map +1 -0
  30. package/package.json +24 -16
  31. package/src/Tooltip.native.tsx +230 -0
  32. package/src/Tooltip.tsx +137 -0
  33. package/src/TooltipArrow.tsx +39 -0
  34. package/src/TooltipContainer.tsx +46 -0
  35. package/src/constants.ts +20 -0
  36. package/src/index.ts +3 -0
  37. package/src/style.ts +370 -0
  38. package/src/type.ts +111 -0
  39. package/src/webStyle.ts +354 -0
  40. package/dist/StyledTooltip/StyledTooltip.d.ts +0 -4
  41. package/dist/StyledTooltip/StyledTooltip.d.ts.map +0 -1
  42. package/dist/StyledTooltip/index.d.ts +0 -2
  43. package/dist/StyledTooltip/index.d.ts.map +0 -1
  44. package/dist/StyledTooltip/style.d.ts +0 -6
  45. package/dist/StyledTooltip/style.d.ts.map +0 -1
  46. package/dist/StyledTooltip/type.d.ts +0 -6
  47. package/dist/StyledTooltip/type.d.ts.map +0 -1
  48. package/dist/TooltipArrow/StyledTooltipArrow/StyledTooltipArrow.d.ts +0 -4
  49. package/dist/TooltipArrow/StyledTooltipArrow/StyledTooltipArrow.d.ts.map +0 -1
  50. package/dist/TooltipArrow/StyledTooltipArrow/index.d.ts +0 -2
  51. package/dist/TooltipArrow/StyledTooltipArrow/index.d.ts.map +0 -1
  52. package/dist/TooltipArrow/StyledTooltipArrow/style.d.ts +0 -7
  53. package/dist/TooltipArrow/StyledTooltipArrow/style.d.ts.map +0 -1
  54. package/dist/TooltipArrow/StyledTooltipArrow/type.d.ts +0 -8
  55. package/dist/TooltipArrow/StyledTooltipArrow/type.d.ts.map +0 -1
  56. package/dist/TooltipArrow/TooltipArrow.d.ts +0 -5
  57. package/dist/TooltipArrow/TooltipArrow.d.ts.map +0 -1
  58. package/dist/TooltipArrow/index.d.ts +0 -2
  59. package/dist/TooltipArrow/index.d.ts.map +0 -1
  60. package/dist/TooltipArrow/style.d.ts +0 -30
  61. package/dist/TooltipArrow/style.d.ts.map +0 -1
  62. package/dist/TooltipArrow/type.d.ts +0 -7
  63. package/dist/TooltipArrow/type.d.ts.map +0 -1
@@ -0,0 +1,170 @@
1
+ import { overlayBorderRadius, positions } from './constants';
2
+ import { Theme } from '@cleartrip/ct-design-theme';
3
+ export declare const getTooltipBorderSize: (borderSize: `${overlayBorderRadius}`, theme: Theme) => {
4
+ borderRadius: 4;
5
+ } | {
6
+ borderRadius: 6;
7
+ } | {
8
+ borderRadius: 8;
9
+ } | {
10
+ borderRadius: 16;
11
+ } | {
12
+ borderRadius: 32;
13
+ };
14
+ export declare const getTooltipAutoPositionStyle: ({ labelRef, tooltipRef, anchorRef, }: {
15
+ labelRef: React.RefObject<HTMLDivElement | null>;
16
+ tooltipRef: React.RefObject<HTMLDivElement | null>;
17
+ anchorRef?: React.RefObject<HTMLElement | null>;
18
+ }) => {
19
+ left: number;
20
+ top: number;
21
+ } | {
22
+ top: number;
23
+ left?: undefined;
24
+ } | {
25
+ left?: undefined;
26
+ top?: undefined;
27
+ };
28
+ export declare const getTooltipBottomPosition: ({ labelRef, tooltipRef, anchorRef, }: {
29
+ labelRef: React.RefObject<HTMLDivElement | null>;
30
+ tooltipRef: React.RefObject<HTMLDivElement | null>;
31
+ anchorRef?: React.RefObject<HTMLElement | null>;
32
+ }) => {
33
+ top: number;
34
+ left: number;
35
+ } | {
36
+ top?: undefined;
37
+ left?: undefined;
38
+ };
39
+ export declare const getTooltipTopPosition: ({ labelRef, tooltipRef, anchorRef, }: {
40
+ labelRef: React.RefObject<HTMLDivElement | null>;
41
+ tooltipRef: React.RefObject<HTMLDivElement | null>;
42
+ anchorRef?: React.RefObject<HTMLElement | null>;
43
+ }) => {
44
+ top: number;
45
+ left: number;
46
+ } | {
47
+ top?: undefined;
48
+ left?: undefined;
49
+ };
50
+ export declare const getTooltipPosition: ({ position, labelRef, tooltipRef, anchorRef, }: {
51
+ position: `${positions}`;
52
+ labelRef: React.RefObject<HTMLDivElement | null>;
53
+ tooltipRef: React.RefObject<HTMLDivElement | null>;
54
+ anchorRef?: React.RefObject<HTMLElement | null>;
55
+ theme: Theme;
56
+ }) => {
57
+ left: number;
58
+ top: number;
59
+ } | {
60
+ top: number;
61
+ left?: undefined;
62
+ } | {
63
+ left?: undefined;
64
+ top?: undefined;
65
+ } | undefined;
66
+ export declare const getTooltipAutoArrowStyles: ({ labelRef, tooltipRef, anchorRef, }: {
67
+ labelRef: React.RefObject<HTMLDivElement | null>;
68
+ tooltipRef: React.RefObject<HTMLDivElement | null>;
69
+ anchorRef?: React.RefObject<HTMLElement | null>;
70
+ }) => {
71
+ top: number;
72
+ left: number;
73
+ rotate?: undefined;
74
+ } | {
75
+ rotate: string;
76
+ left: number;
77
+ top: number;
78
+ } | {
79
+ top?: undefined;
80
+ left?: undefined;
81
+ rotate?: undefined;
82
+ };
83
+ export declare const getTooltipArrowStyles: ({ position, labelRef, tooltipRef, anchorRef, }: {
84
+ position: `${positions}`;
85
+ labelRef: React.RefObject<HTMLDivElement | null>;
86
+ tooltipRef: React.RefObject<HTMLDivElement | null>;
87
+ anchorRef?: React.RefObject<HTMLElement | null>;
88
+ theme: Theme;
89
+ }) => {
90
+ top: number;
91
+ left: number;
92
+ rotate?: undefined;
93
+ } | {
94
+ rotate: string;
95
+ left: number;
96
+ top: number;
97
+ } | {
98
+ top?: undefined;
99
+ left?: undefined;
100
+ rotate?: undefined;
101
+ };
102
+ export declare const getTooltipStyles: ({ borderSize, position, labelRef, tooltipRef, anchorRef, theme, }: {
103
+ borderSize: `${overlayBorderRadius}`;
104
+ position: `${positions}`;
105
+ labelRef: React.RefObject<HTMLDivElement | null>;
106
+ tooltipRef: React.RefObject<HTMLDivElement | null>;
107
+ anchorRef?: React.RefObject<HTMLElement | null>;
108
+ theme: Theme;
109
+ }) => {
110
+ borderRadius: 4;
111
+ left: number;
112
+ top: number;
113
+ } | {
114
+ borderRadius: 6;
115
+ left: number;
116
+ top: number;
117
+ } | {
118
+ borderRadius: 8;
119
+ left: number;
120
+ top: number;
121
+ } | {
122
+ borderRadius: 16;
123
+ left: number;
124
+ top: number;
125
+ } | {
126
+ borderRadius: 32;
127
+ left: number;
128
+ top: number;
129
+ } | {
130
+ borderRadius: 4;
131
+ top: number;
132
+ left?: undefined;
133
+ } | {
134
+ borderRadius: 6;
135
+ top: number;
136
+ left?: undefined;
137
+ } | {
138
+ borderRadius: 8;
139
+ top: number;
140
+ left?: undefined;
141
+ } | {
142
+ borderRadius: 16;
143
+ top: number;
144
+ left?: undefined;
145
+ } | {
146
+ borderRadius: 32;
147
+ top: number;
148
+ left?: undefined;
149
+ } | {
150
+ borderRadius: 4;
151
+ left?: undefined;
152
+ top?: undefined;
153
+ } | {
154
+ borderRadius: 6;
155
+ left?: undefined;
156
+ top?: undefined;
157
+ } | {
158
+ borderRadius: 8;
159
+ left?: undefined;
160
+ top?: undefined;
161
+ } | {
162
+ borderRadius: 16;
163
+ left?: undefined;
164
+ top?: undefined;
165
+ } | {
166
+ borderRadius: 32;
167
+ left?: undefined;
168
+ top?: undefined;
169
+ };
170
+ //# sourceMappingURL=webStyle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webStyle.d.ts","sourceRoot":"","sources":["../packages/components/Tooltip/src/webStyle.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@cleartrip/ct-design-tooltip",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Tooltip Component",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/ct-design-tooltip.cjs.js",
7
7
  "jsnext:main": "dist/ct-design-tooltip.esm.js",
8
+ "react-native": "src/index.ts",
8
9
  "module": "dist/ct-design-tooltip.esm.js",
9
10
  "sideEffects": false,
10
11
  "browser": {
@@ -12,24 +13,29 @@
12
13
  "./dist/ct-design-tooltip.cjs.js": "./dist/ct-design-tooltip.browser.cjs.js"
13
14
  },
14
15
  "files": [
15
- "dist"
16
+ "dist",
17
+ "src"
16
18
  ],
17
19
  "dependencies": {
18
- "@cleartrip/ct-design-types": "4.0.0",
19
- "@cleartrip/ct-design-transition": "4.0.0",
20
- "@cleartrip/ct-design-conditional-wrap": "4.0.0",
21
- "@cleartrip/ct-design-portal": "4.0.0",
22
- "@cleartrip/ct-design-theme": "4.0.0",
23
- "@cleartrip/ct-design-use-merge-refs": "4.0.0",
24
- "@cleartrip/ct-design-icons": "26.0.0",
25
- "@cleartrip/ct-design-use-isomorphic-effect": "4.0.0",
26
- "@cleartrip/ct-design-container": "4.0.0"
20
+ "@emotion/react": "^11.14.0",
21
+ "@emotion/styled": "^11.14.0",
22
+ "@cleartrip/ct-design-theme": "5.0.0",
23
+ "@cleartrip/ct-design-container": "5.0.0",
24
+ "@cleartrip/ct-design-common-utils": "5.0.0",
25
+ "@cleartrip/ct-design-use-merge-refs": "5.0.0",
26
+ "@cleartrip/ct-design-icons": "5.0.0",
27
+ "@cleartrip/ct-design-style-manager": "5.0.0",
28
+ "@cleartrip/ct-design-conditional-wrap": "5.0.0",
29
+ "@cleartrip/ct-design-transition": "5.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "@emotion/babel-plugin": "^11.12.0",
33
+ "@cleartrip/ct-design-typography": "5.0.0",
34
+ "@cleartrip/ct-design-types": "5.0.0"
27
35
  },
28
- "devDependencies": {},
29
36
  "peerDependencies": {
30
37
  "react": ">=16.8.0",
31
- "react-dom": ">=16.8.0",
32
- "styled-components": "^5.3.6"
38
+ "react-dom": ">=16.8.0"
33
39
  },
34
40
  "publishConfig": {
35
41
  "access": "public"
@@ -38,8 +44,10 @@
38
44
  "license": "ISC",
39
45
  "scripts": {
40
46
  "test": "echo \"Error: no test specified\" && exit 1",
41
- "watch-package": "rollup -c -w",
42
47
  "build-package": "rollup -c",
43
- "build-package:clean": "rm -rf dist && rollup -c"
48
+ "build-package:clean": "rm -rf dist && rollup -c",
49
+ "publish-package:local": "yalc publish --no-scripts",
50
+ "watch-package": "rollup -c -w",
51
+ "publish-package:local:registry": "pnpm publish --registry http://localhost:4873 --no-git-checks --access public"
44
52
  }
45
53
  }
@@ -0,0 +1,230 @@
1
+ import React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
2
+
3
+ import { Pressable, View } from 'react-native';
4
+ import Animated, { Easing, useSharedValue, withTiming } from 'react-native-reanimated';
5
+ import { useNativeMergeStyles, useStyles } from '@cleartrip/ct-design-style-manager';
6
+ import { Container, ContainerRef } from '@cleartrip/ct-design-container';
7
+ import { Typography } from '@cleartrip/ct-design-typography';
8
+ import Conditional from '@cleartrip/ct-design-conditional-wrap';
9
+ import { TooltipChevronDown } from '@cleartrip/ct-design-icons';
10
+
11
+ import { getTooltipArrowStyles, getTooltipOverlayStyles, staticTooltipStyles } from './style';
12
+ import { IDimensionsProps, IMeasurements, ITooltipProps } from './type';
13
+ import { Theme } from '@cleartrip/ct-design-theme';
14
+
15
+ export const getDefaultTooltipStyles = (theme: Theme) => {
16
+ return {
17
+ backgroundColor: theme.color.tooltip.primaryBg,
18
+ borderRadius: theme.border.radius[4],
19
+ };
20
+ };
21
+
22
+ const initialDimensions: IDimensionsProps = {
23
+ width: 0,
24
+ height: 0,
25
+ x: 0,
26
+ y: 0,
27
+ leftEdge: 0,
28
+ rightEdge: 0,
29
+ };
30
+
31
+ const measure = (ref: React.RefObject<View | null>): Promise<IDimensionsProps> => {
32
+ return new Promise((resolve) => {
33
+ ref.current?.measure((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => {
34
+ if (width !== undefined && height !== undefined && pageX !== undefined && pageY !== undefined) {
35
+ resolve({
36
+ width: Math.floor(width),
37
+ height: Math.floor(height),
38
+ x: Math.floor(x),
39
+ y: Math.floor(y),
40
+ leftEdge: pageX,
41
+ rightEdge: pageX + Math.floor(width),
42
+ });
43
+ } else {
44
+ resolve(initialDimensions);
45
+ }
46
+ });
47
+ });
48
+ };
49
+
50
+ const Tooltip = forwardRef<ContainerRef, ITooltipProps>(
51
+ (
52
+ {
53
+ children,
54
+ position = 'right',
55
+ labelContainer,
56
+ tooltipWidth = 150,
57
+ tooltipBorderRadius = 'md',
58
+ styleConfig,
59
+ open = false,
60
+ animate = true,
61
+ svgPathProps,
62
+ anchorRef,
63
+ },
64
+ ref,
65
+ ) => {
66
+ const {
67
+ root: customRootStyles = [],
68
+ labelContainerStyles: customLabelContainerStyles = [],
69
+ overlayStyles: customOverlayStyles = [],
70
+ arrowStyles: customArrowStyles = [],
71
+ } = styleConfig || {};
72
+ const [isHovered, setIsHovered] = useState<boolean>(open);
73
+ const labelContainerRef = useRef<View>(null);
74
+ const overlayRef = useRef<View>(null);
75
+ const fadeAnim = useSharedValue(0);
76
+ const [measurements, setMeasurements] = useState<IMeasurements>({
77
+ labelContainer: initialDimensions,
78
+ overlayContainer: initialDimensions,
79
+ anchorRef: initialDimensions,
80
+ });
81
+
82
+ const dynamicTooltipStyles = useStyles(
83
+ (theme) => {
84
+ return {
85
+ overlayStyles: {
86
+ opacity: isHovered ? 1 : 0,
87
+ width: tooltipWidth,
88
+ ...getTooltipOverlayStyles({
89
+ theme,
90
+ borderRadius: tooltipBorderRadius,
91
+ overlayWidth: tooltipWidth,
92
+ position,
93
+ measurements,
94
+ }),
95
+ },
96
+ };
97
+ },
98
+ [position, measurements, tooltipWidth, isHovered, tooltipBorderRadius],
99
+ );
100
+
101
+ const dynamicTooltipArrowStyles = useStyles(() => {
102
+ return {
103
+ tooltipArrow: {
104
+ opacity: isHovered ? 1 : 0,
105
+ ...getTooltipArrowStyles({
106
+ position,
107
+ measurements,
108
+ }),
109
+ },
110
+ };
111
+ }, [isHovered, position, measurements]);
112
+
113
+ const mergedLabelContainerStyles = useNativeMergeStyles(
114
+ [staticTooltipStyles?.labelContainerStyles, ...customLabelContainerStyles],
115
+ [customLabelContainerStyles],
116
+ );
117
+
118
+ const handleLayout = useCallback(() => {
119
+ const calculatePosition = async () => {
120
+ try {
121
+ const labelContainer = await measure(labelContainerRef);
122
+ const overlayContainer = await measure(overlayRef);
123
+
124
+ /**
125
+ * force type casting
126
+ */
127
+ const wrapper = anchorRef ? await measure(anchorRef as React.RefObject<View>) : initialDimensions;
128
+
129
+ setMeasurements({
130
+ labelContainer,
131
+ overlayContainer,
132
+ anchorRef: wrapper,
133
+ });
134
+ } catch (_error) {
135
+ // Error handling without console.log
136
+ }
137
+ };
138
+
139
+ calculatePosition();
140
+ }, [anchorRef]);
141
+
142
+ const handlePress = useCallback((isVisible: boolean) => setIsHovered(isVisible), []);
143
+
144
+ useEffect(() => {
145
+ if (isHovered) {
146
+ if (animate) {
147
+ fadeAnim.value = withTiming(1, {
148
+ duration: 200,
149
+ easing: Easing.inOut(Easing.ease),
150
+ });
151
+ } else {
152
+ fadeAnim.value = 1;
153
+ }
154
+ } else {
155
+ if (animate) {
156
+ fadeAnim.value = withTiming(0, {
157
+ duration: 200,
158
+ easing: Easing.inOut(Easing.ease),
159
+ });
160
+ } else {
161
+ fadeAnim.value = 0;
162
+ }
163
+ }
164
+ }, [isHovered, fadeAnim, animate]);
165
+
166
+ useEffect(() => {
167
+ setIsHovered(open);
168
+ }, [open]);
169
+
170
+ return (
171
+ <Container
172
+ ref={ref}
173
+ styleConfig={{ root: [staticTooltipStyles?.root, ...customRootStyles] }}
174
+ onLayout={handleLayout}
175
+ >
176
+ <Pressable
177
+ ref={labelContainerRef}
178
+ style={mergedLabelContainerStyles}
179
+ onPressIn={() => handlePress(true)}
180
+ onPressOut={() => handlePress(false)}
181
+ >
182
+ {labelContainer}
183
+ </Pressable>
184
+
185
+ {!!children && (
186
+ <>
187
+ <Animated.View style={{ opacity: fadeAnim, position: 'absolute' }}>
188
+ <View ref={overlayRef}>
189
+ <Container
190
+ styleConfig={{
191
+ root: [
192
+ staticTooltipStyles?.overlayStyles,
193
+ dynamicTooltipStyles?.overlayStyles,
194
+ ...customOverlayStyles,
195
+ ],
196
+ }}
197
+ >
198
+ <Conditional
199
+ condition={typeof children === 'string'}
200
+ wrap={() => (
201
+ <Typography variant='B2' color='neutral'>
202
+ {children}
203
+ </Typography>
204
+ )}
205
+ >
206
+ {children}
207
+ </Conditional>
208
+ </Container>
209
+
210
+ <Container
211
+ styleConfig={{
212
+ root: [
213
+ staticTooltipStyles?.tooltipArrow,
214
+ dynamicTooltipArrowStyles?.tooltipArrow,
215
+ ...customArrowStyles,
216
+ ],
217
+ }}
218
+ >
219
+ <TooltipChevronDown {...svgPathProps} />
220
+ </Container>
221
+ </View>
222
+ </Animated.View>
223
+ </>
224
+ )}
225
+ </Container>
226
+ );
227
+ },
228
+ );
229
+ Tooltip.displayName = 'Tooltip';
230
+ export default Tooltip;
@@ -0,0 +1,137 @@
1
+ import { MouseEvent, useEffect, useRef, useState, useCallback } from 'react';
2
+ import { useTheme } from '@cleartrip/ct-design-theme';
3
+ import { Container } from '@cleartrip/ct-design-container';
4
+ import Conditional from '@cleartrip/ct-design-conditional-wrap';
5
+
6
+ import { ITooltipProps, TooltipStyles, TooltipArrowStyles } from './type';
7
+ import { overlayBorderRadius, positions } from './constants';
8
+ import { staticTooltipStyles } from './style';
9
+ import TooltipContainer from './TooltipContainer';
10
+ import TooltipArrow from './TooltipArrow';
11
+ import { Transition } from '@cleartrip/ct-design-transition';
12
+ import { TooltipChevronDown } from '@cleartrip/ct-design-icons';
13
+ import { useStyles, useWebMergeStyles } from '@cleartrip/ct-design-style-manager';
14
+ import { isEmpty } from '@cleartrip/ct-design-common-utils';
15
+ import { getTooltipStyles, getTooltipArrowStyles } from './webStyle';
16
+
17
+ const Tooltip: React.FC<ITooltipProps> = ({
18
+ children,
19
+ position = positions.RIGHT,
20
+ labelContainer,
21
+ tooltipWidth = 150,
22
+ tooltipBorderRadius = overlayBorderRadius.MD,
23
+ styleConfig,
24
+ enableTooltipContainerHovering = false,
25
+ open = false,
26
+ animate = true,
27
+ svgPathProps,
28
+ anchorRef,
29
+ }) => {
30
+ const theme = useTheme();
31
+ const {
32
+ root: customRootStyles = [],
33
+ labelContainerStyles: customLabelContainerStyles = [],
34
+ overlayStyles: customOverlayStyles = [],
35
+ arrowStyles: customArrowStyles = [],
36
+ } = styleConfig || {};
37
+ const [styles, setStyles] = useState<{ tooltipStyles: TooltipStyles; tooltipArrowStyles: TooltipArrowStyles }>({
38
+ tooltipStyles: {},
39
+ tooltipArrowStyles: {},
40
+ });
41
+ const labelRef = useRef<HTMLDivElement>(null);
42
+ const tooltipRef = useRef<HTMLDivElement>(null);
43
+
44
+ const setTooltipStyles = useCallback(() => {
45
+ const tooltipStyle = getTooltipStyles({
46
+ borderSize: tooltipBorderRadius,
47
+ position,
48
+ labelRef,
49
+ tooltipRef,
50
+ anchorRef: anchorRef as React.RefObject<HTMLElement | null>,
51
+ theme,
52
+ });
53
+
54
+ const tooltipArrowStyle = getTooltipArrowStyles({
55
+ position,
56
+ labelRef,
57
+ tooltipRef,
58
+ anchorRef: anchorRef as React.RefObject<HTMLElement | null>,
59
+ theme,
60
+ });
61
+ setStyles({ tooltipStyles: tooltipStyle, tooltipArrowStyles: tooltipArrowStyle });
62
+ }, [tooltipBorderRadius, position, labelRef, tooltipRef, anchorRef, theme]);
63
+
64
+ useEffect(() => {
65
+ if (open) {
66
+ setTooltipStyles();
67
+ } else {
68
+ setStyles({ tooltipStyles: {}, tooltipArrowStyles: {} });
69
+ }
70
+ }, [open, setTooltipStyles]);
71
+
72
+ const canCloseTooltipContainer = (event: MouseEvent<HTMLDivElement>) => {
73
+ const defaultDimesstions = { right: 0, left: 0, bottom: 0, top: 0 };
74
+ const tooltipDimesntions = tooltipRef.current?.getBoundingClientRect() ?? defaultDimesstions;
75
+ const labelDimensions = labelRef.current?.getBoundingClientRect() ?? defaultDimesstions;
76
+
77
+ const { r, l, b, t } = {
78
+ r: Math.floor(Math.max(tooltipDimesntions.right, labelDimensions.left)),
79
+ l: Math.floor(Math.min(tooltipDimesntions.left, labelDimensions.right)),
80
+ b: Math.floor(Math.max(tooltipDimesntions.bottom, labelDimensions.top)),
81
+ t: Math.floor(Math.min(tooltipDimesntions.top, labelDimensions.bottom)),
82
+ };
83
+
84
+ const currentX = event.clientX + 1;
85
+ const currentY = event.clientY + 1;
86
+
87
+ return r >= currentX && l <= currentX && t <= currentY && b >= currentY;
88
+ };
89
+ const handleMouseEnter = () => {
90
+ setTooltipStyles();
91
+ };
92
+
93
+ const handleMouseLeave = (event: MouseEvent<HTMLDivElement>) => {
94
+ if (enableTooltipContainerHovering && canCloseTooltipContainer(event)) return;
95
+ setStyles({ tooltipStyles: {}, tooltipArrowStyles: {} });
96
+ };
97
+
98
+ const labelStyles = useWebMergeStyles([...customLabelContainerStyles], [customLabelContainerStyles]);
99
+
100
+ const dynamicTooltipStyles = useStyles(() => {
101
+ return {
102
+ tooltip: styles.tooltipStyles,
103
+ tooltipArrow: styles.tooltipArrowStyles,
104
+ };
105
+ }, [styles.tooltipStyles, open]);
106
+
107
+ return (
108
+ <Container styleConfig={{ root: [staticTooltipStyles?.root, ...customRootStyles] }}>
109
+ <div onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} ref={labelRef} className={labelStyles}>
110
+ {labelContainer}
111
+ </div>
112
+ {!!children && (
113
+ <Conditional condition={animate} wrap={(child) => <Transition type='fade'>{child}</Transition>}>
114
+ <>
115
+ <TooltipContainer
116
+ visible={!isEmpty(styles.tooltipStyles)}
117
+ width={tooltipWidth}
118
+ onMouseLeave={handleMouseLeave}
119
+ styleConfig={{ root: [dynamicTooltipStyles.tooltip, ...customOverlayStyles] }}
120
+ tooltipRef={tooltipRef}
121
+ >
122
+ {children}
123
+ </TooltipContainer>
124
+ <TooltipArrow
125
+ visible={!isEmpty(styles.tooltipArrowStyles)}
126
+ styleConfig={{ root: [dynamicTooltipStyles.tooltipArrow, ...customArrowStyles] }}
127
+ >
128
+ <TooltipChevronDown {...svgPathProps} />
129
+ </TooltipArrow>
130
+ </>
131
+ </Conditional>
132
+ )}
133
+ </Container>
134
+ );
135
+ };
136
+
137
+ export default Tooltip;
@@ -0,0 +1,39 @@
1
+ import { makeStyles, useWebMergeStyles } from '@cleartrip/ct-design-style-manager';
2
+ import { css } from '@emotion/css';
3
+ import { Styles } from '@cleartrip/ct-design-types';
4
+ import { useMemo } from 'react';
5
+
6
+ const staticStyles = makeStyles((theme) => ({
7
+ root: {
8
+ zIndex: theme.zIndex.tooltip,
9
+ position: 'absolute',
10
+ display: 'flex',
11
+ },
12
+ }));
13
+
14
+ const webStaticStyles = css({
15
+ width: 'fit-content',
16
+ });
17
+
18
+ const TooltipArrow: React.FC<{
19
+ children: React.ReactElement;
20
+ visible: boolean;
21
+ styleConfig: {
22
+ root: Styles[];
23
+ };
24
+ }> = ({ children, visible, styleConfig }) => {
25
+ const tooltipArrowClass = useMemo(
26
+ () =>
27
+ css({
28
+ visibility: visible ? 'visible' : 'hidden',
29
+ }),
30
+ [visible],
31
+ );
32
+ const arrowClass = useWebMergeStyles(
33
+ [staticStyles.root, webStaticStyles, tooltipArrowClass, ...styleConfig.root],
34
+ [tooltipArrowClass, styleConfig.root],
35
+ );
36
+ return <div className={arrowClass}>{children}</div>;
37
+ };
38
+
39
+ export default TooltipArrow;
@@ -0,0 +1,46 @@
1
+ import React, { useMemo } from 'react';
2
+
3
+ import { makeStyles, useWebMergeStyles } from '@cleartrip/ct-design-style-manager';
4
+ import { Styles, ViewStyle } from '@cleartrip/ct-design-types';
5
+ import { css } from '@emotion/css';
6
+
7
+ const staticStyles = makeStyles((theme) => ({
8
+ root: {
9
+ backgroundColor: theme.color.background.defaultDarkest,
10
+ position: 'absolute',
11
+ zIndex: theme.zIndex.tooltip,
12
+ },
13
+ }));
14
+
15
+ const TooltipContainer: React.FC<{
16
+ children: React.ReactElement;
17
+ visible: boolean;
18
+ width: ViewStyle['width'];
19
+ onMouseLeave: (event: React.MouseEvent<HTMLDivElement>) => void;
20
+ tooltipRef: React.RefObject<HTMLDivElement | null>;
21
+ styleConfig: {
22
+ root: Styles[];
23
+ };
24
+ }> = ({ children, visible, width, onMouseLeave, tooltipRef, styleConfig }) => {
25
+ const tooltipClass = useMemo(
26
+ () =>
27
+ css({
28
+ width: width ?? 'auto',
29
+ visibility: visible ? 'visible' : 'hidden',
30
+ }),
31
+ [width, visible],
32
+ );
33
+ const containerClass = useWebMergeStyles(
34
+ [staticStyles.root, tooltipClass, ...styleConfig.root],
35
+ [styleConfig.root, tooltipClass],
36
+ );
37
+ return (
38
+ <div ref={tooltipRef} className={containerClass} onMouseLeave={onMouseLeave}>
39
+ {children}
40
+ </div>
41
+ );
42
+ };
43
+
44
+ TooltipContainer.displayName = 'TooltipContainer';
45
+
46
+ export default TooltipContainer;