@cleartrip/ct-design-tooltip 4.0.0 → 5.1.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,20 @@
1
+ export enum positions {
2
+ TOP = 'top',
3
+ RIGHT = 'right',
4
+ BOTTOM = 'bottom',
5
+ LEFT = 'left',
6
+ AUTO = 'auto',
7
+ }
8
+
9
+ export enum overlayBorderRadius {
10
+ XS = 'xs',
11
+ SM = 'sm',
12
+ MD = 'md',
13
+ LG = 'lg',
14
+ XL = 'xl',
15
+ }
16
+
17
+ export enum HOVER_TYPE {
18
+ ENTER = 'ENTER',
19
+ LEAVE = 'LEAVE',
20
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { default as Tooltip } from './Tooltip';
2
+ export type * from './type';
3
+ export * from './constants';
package/src/style.ts ADDED
@@ -0,0 +1,370 @@
1
+ import { Theme } from '@cleartrip/ct-design-theme';
2
+ import { makeStyles } from '@cleartrip/ct-design-style-manager';
3
+ import { getDeviceHeight, getDeviceWidth, isMobile } from '@cleartrip/ct-design-common-utils';
4
+
5
+ import { IMeasurements } from './type';
6
+ import { overlayBorderRadius, positions } from './constants';
7
+ import { ViewStyle } from '@cleartrip/ct-design-types';
8
+
9
+ export type positionType = `${positions}`;
10
+ export type overlayBorderRadiusType = `${overlayBorderRadius}`;
11
+
12
+ export const staticTooltipStyles = makeStyles((theme) => {
13
+ return {
14
+ root: {
15
+ position: 'relative',
16
+ },
17
+ labelContainerStyles: {
18
+ width: (isMobile() ? 100 : 'fit-content') as unknown as number,
19
+ flexDirection: 'row',
20
+ },
21
+ overlayStyles: {
22
+ flexDirection: 'row',
23
+ position: 'absolute',
24
+ width: theme?.size[50],
25
+ zIndex: theme?.zIndex.tooltip,
26
+ backgroundColor: theme?.color.background.defaultDarkest,
27
+ paddingVertical: theme?.spacing[1],
28
+ paddingHorizontal: theme?.spacing[2],
29
+ borderRadius: theme?.border.radius[8],
30
+ },
31
+ tooltipArrow: {
32
+ display: 'flex',
33
+ position: 'absolute',
34
+ zIndex: theme?.zIndex.tooltip,
35
+ },
36
+ };
37
+ });
38
+
39
+ const getTooltipArrowAutoPositionStyle = ({ measurements }: { measurements: IMeasurements }) => {
40
+ const { labelContainer, overlayContainer } = measurements;
41
+ const screenWidth = getDeviceWidth();
42
+ const screenHeight = getDeviceHeight();
43
+
44
+ if (labelContainer && overlayContainer) {
45
+ const tooltipHeight = overlayContainer.height ?? 0;
46
+ const labelHeight = labelContainer.height ?? 0;
47
+ const labelWidth = labelContainer.width ?? 0;
48
+ const labelLeftEdge = labelContainer.leftEdge ?? 0;
49
+ const labelRightEdge = labelContainer.rightEdge ?? 0;
50
+
51
+ // Calculate available space in each direction
52
+ const spaceAbove = labelContainer.y;
53
+ const spaceBelow = screenHeight - (labelContainer.y + labelHeight);
54
+ const spaceLeft = labelLeftEdge;
55
+ const spaceRight = screenWidth - labelRightEdge;
56
+
57
+ // Determine arrow position based on tooltip position
58
+ if (spaceBelow >= tooltipHeight + 10) {
59
+ return {
60
+ transform: `rotate(180deg)`,
61
+ top: labelHeight + 5,
62
+ left: labelWidth / 2,
63
+ };
64
+ } else if (spaceAbove >= tooltipHeight + 10) {
65
+ return {
66
+ top: -11,
67
+ left: labelWidth / 2,
68
+ };
69
+ } else if (spaceRight >= overlayContainer.width + 10) {
70
+ return {
71
+ transform: `rotate(90deg)`,
72
+ top: labelHeight - 15,
73
+ left: labelWidth - 1,
74
+ };
75
+ } else if (spaceLeft >= overlayContainer.width + 10) {
76
+ return {
77
+ transform: `rotate(-90deg)`,
78
+ top: labelHeight - 15,
79
+ left: -16,
80
+ };
81
+ }
82
+
83
+ // Default to bottom arrow if no space is available
84
+ return {
85
+ transform: `rotate(180deg)`,
86
+ top: labelHeight + 5,
87
+ left: labelWidth / 2,
88
+ };
89
+ }
90
+
91
+ return { left: 0, top: 0 };
92
+ };
93
+
94
+ export const getOverlayTopPosition = ({ measurements }: { measurements: IMeasurements }) => {
95
+ const tooltipWidth = measurements?.overlayContainer.width || 0;
96
+ const labelWidth = measurements?.labelContainer?.width || 0;
97
+ const screenWidth = getDeviceWidth();
98
+ const leftEdge = measurements.labelContainer.leftEdge || 0;
99
+ const rightEdge = measurements.labelContainer.rightEdge || 0;
100
+ let leftPosition = 0;
101
+
102
+ if (tooltipWidth > labelWidth) {
103
+ const labelCenter = (leftEdge + rightEdge) / 2;
104
+
105
+ leftPosition = (labelCenter - tooltipWidth) / 2;
106
+
107
+ if (leftPosition < 0) {
108
+ leftPosition = 0;
109
+ } else if (leftPosition + tooltipWidth > screenWidth) {
110
+ leftPosition = screenWidth - tooltipWidth;
111
+ }
112
+ } else {
113
+ leftPosition = labelWidth / 2 - tooltipWidth / 2;
114
+
115
+ if (leftPosition < 0) {
116
+ leftPosition = 0;
117
+ } else if (leftPosition + tooltipWidth > screenWidth) {
118
+ leftPosition = screenWidth - tooltipWidth;
119
+ }
120
+ }
121
+
122
+ return {
123
+ top: -(measurements?.overlayContainer?.height + 10),
124
+ left: leftPosition,
125
+ };
126
+ };
127
+
128
+ export const getOverlayBottomPosition = ({ measurements }: { measurements: IMeasurements }) => {
129
+ const tooltipWidth = measurements?.overlayContainer.width || 0;
130
+ const labelWidth = measurements?.labelContainer?.width || 0;
131
+ const screenWidth = getDeviceWidth();
132
+ const leftEdge = measurements.labelContainer.leftEdge || 0;
133
+ const rightEdge = measurements.labelContainer.rightEdge || 0;
134
+ let leftPosition = 0;
135
+
136
+ if (tooltipWidth > labelWidth) {
137
+ const labelCenter = (leftEdge + rightEdge) / 2;
138
+
139
+ leftPosition = (labelCenter - tooltipWidth) / 2;
140
+
141
+ if (leftPosition < 0) {
142
+ leftPosition = 0;
143
+ } else if (leftPosition + tooltipWidth > screenWidth) {
144
+ leftPosition = screenWidth - tooltipWidth;
145
+ }
146
+ } else {
147
+ leftPosition = labelWidth / 2 - tooltipWidth / 2;
148
+
149
+ if (leftPosition < 0) {
150
+ leftPosition = 0;
151
+ } else if (leftPosition + tooltipWidth > screenWidth) {
152
+ leftPosition = screenWidth - tooltipWidth;
153
+ }
154
+ }
155
+
156
+ return {
157
+ top: measurements.labelContainer.height + 10,
158
+ left: leftPosition,
159
+ };
160
+ };
161
+
162
+ export const getTooltipAutoPositionStyle = ({ measurements }: { measurements: IMeasurements }) => {
163
+ const { labelContainer, overlayContainer } = measurements;
164
+ const screenWidth = getDeviceWidth();
165
+ const screenHeight = getDeviceHeight();
166
+
167
+ // Ensure labelContainer and overlayContainer are defined
168
+ if (labelContainer && overlayContainer) {
169
+ const tooltipHeight = overlayContainer.height ?? 0;
170
+ const tooltipWidth = overlayContainer.width ?? 0;
171
+ const labelHeight = labelContainer.height ?? 0;
172
+ const labelWidth = labelContainer.width ?? 0;
173
+ const labelLeftEdge = labelContainer.leftEdge ?? 0;
174
+ const labelRightEdge = labelContainer.rightEdge ?? 0;
175
+
176
+ // Calculate available space in each direction
177
+ const spaceAbove = labelContainer.y;
178
+ const spaceBelow = screenHeight - (labelContainer.y + labelHeight);
179
+ const spaceLeft = labelLeftEdge;
180
+ const spaceRight = screenWidth - labelRightEdge;
181
+
182
+ // Determine best position based on available space
183
+ if (spaceBelow >= tooltipHeight + 10) {
184
+ return getOverlayBottomPosition({ measurements });
185
+ } else if (spaceAbove >= tooltipHeight + 10) {
186
+ return getOverlayTopPosition({ measurements });
187
+ } else if (spaceRight >= tooltipWidth + 10) {
188
+ return {
189
+ left: labelWidth + 10,
190
+ top: -(tooltipHeight / 2 - labelHeight / 2),
191
+ };
192
+ } else if (spaceLeft >= tooltipWidth + 10) {
193
+ return {
194
+ left: -(tooltipWidth + 10),
195
+ top: -(tooltipHeight / 2 - labelHeight / 2),
196
+ };
197
+ }
198
+
199
+ // Default to bottom if no space is available
200
+ return getOverlayBottomPosition({ measurements });
201
+ }
202
+
203
+ return { left: 0, top: 0 };
204
+ };
205
+
206
+ export const getOverlayPositionStyles = ({
207
+ position,
208
+ measurements,
209
+ }: {
210
+ position: positionType;
211
+ measurements: IMeasurements;
212
+ }) => {
213
+ const labelHeight = measurements.labelContainer.height;
214
+ const labelWidth = measurements.labelContainer.width;
215
+ const tooltipHeight = measurements.overlayContainer.height;
216
+ const tooltipWidth = measurements.overlayContainer.width;
217
+ switch (position) {
218
+ case positions.TOP: {
219
+ return {
220
+ ...getOverlayTopPosition({ measurements }),
221
+ };
222
+ }
223
+ case positions.RIGHT: {
224
+ return {
225
+ left: labelWidth + 10,
226
+ top: -(tooltipHeight / 2 - labelHeight / 2),
227
+ };
228
+ }
229
+ case positions.BOTTOM: {
230
+ return {
231
+ ...getOverlayBottomPosition({ measurements }),
232
+ };
233
+ }
234
+ case positions.LEFT: {
235
+ return {
236
+ left: -(tooltipWidth + 10),
237
+ top: -(tooltipHeight / 2 - labelHeight / 2),
238
+ };
239
+ }
240
+ case positions.AUTO: {
241
+ return { ...getTooltipAutoPositionStyle({ measurements }) };
242
+ }
243
+
244
+ default: {
245
+ return {
246
+ left: 0,
247
+ };
248
+ }
249
+ }
250
+ };
251
+
252
+ export const getOverlayBorderStyles = ({
253
+ theme,
254
+ borderRadius,
255
+ }: {
256
+ theme: Theme;
257
+ borderRadius: `${overlayBorderRadius}`;
258
+ }) => {
259
+ switch (borderRadius) {
260
+ case overlayBorderRadius.XS: {
261
+ return {
262
+ borderRadius: theme.border.radius[4],
263
+ };
264
+ }
265
+ case overlayBorderRadius.SM: {
266
+ return {
267
+ borderRadius: theme.border.radius[6],
268
+ };
269
+ }
270
+ case overlayBorderRadius.MD: {
271
+ return {
272
+ borderRadius: theme.border.radius[8],
273
+ };
274
+ }
275
+ case overlayBorderRadius.LG: {
276
+ return {
277
+ borderRadius: theme.border.radius[16],
278
+ };
279
+ }
280
+ case overlayBorderRadius.XL: {
281
+ return {
282
+ borderRadius: theme.border.radius[32],
283
+ };
284
+ }
285
+
286
+ default: {
287
+ return {
288
+ borderRadius: theme.border.radius[8],
289
+ };
290
+ }
291
+ }
292
+ };
293
+
294
+ export const getTooltipOverlayStyles = ({
295
+ theme,
296
+ position,
297
+ borderRadius,
298
+ measurements,
299
+ }: {
300
+ theme: Theme;
301
+ overlayWidth: ViewStyle['width'];
302
+ position: `${positionType}`;
303
+ borderRadius: `${overlayBorderRadius}`;
304
+ measurements: IMeasurements;
305
+ }) => {
306
+ return {
307
+ ...getOverlayPositionStyles({ position, measurements }),
308
+ ...getOverlayBorderStyles({ theme, borderRadius }),
309
+ };
310
+ };
311
+
312
+ // ---------- ARROW STYLES ----------------- //
313
+
314
+ const getTooltipArrowPosition = ({
315
+ position,
316
+ measurements,
317
+ }: {
318
+ position: `${positionType}`;
319
+ measurements: IMeasurements;
320
+ }) => {
321
+ const labelWidth = measurements?.labelContainer.width || 0;
322
+ const labelHeight = measurements?.labelContainer.height || 0;
323
+
324
+ switch (position) {
325
+ case positions.TOP: {
326
+ return {
327
+ top: -11,
328
+ left: labelWidth / 2,
329
+ };
330
+ }
331
+ case positions.BOTTOM: {
332
+ return {
333
+ transform: `rotate(180deg)`,
334
+ top: labelHeight + 5,
335
+ left: labelWidth / 2,
336
+ };
337
+ }
338
+ case positions.LEFT: {
339
+ return {
340
+ transform: `rotate(-90deg)`,
341
+ top: labelHeight - 15,
342
+ left: -16,
343
+ };
344
+ }
345
+ case positions.RIGHT: {
346
+ return {
347
+ transform: `rotate(90deg)`,
348
+ top: labelHeight - 15,
349
+ left: labelWidth - 1,
350
+ };
351
+ }
352
+ case positions.AUTO: {
353
+ return {
354
+ ...getTooltipArrowAutoPositionStyle({ measurements }),
355
+ };
356
+ }
357
+ }
358
+ };
359
+
360
+ export const getTooltipArrowStyles = ({
361
+ position,
362
+ measurements,
363
+ }: {
364
+ position: `${positionType}`;
365
+ measurements: IMeasurements;
366
+ }) => {
367
+ return {
368
+ ...getTooltipArrowPosition({ position, measurements }),
369
+ };
370
+ };
package/src/type.ts ADDED
@@ -0,0 +1,111 @@
1
+ import { Styles, ViewStyle } from '@cleartrip/ct-design-types';
2
+ import { ReactElement, SVGProps } from 'react';
3
+
4
+ import { positions, overlayBorderRadius } from './constants';
5
+ export interface ITooltipProps {
6
+ /**
7
+ * The content to be displayed inside the tooltip.
8
+ */
9
+ children: ReactElement;
10
+
11
+ /**
12
+ * The container for the label of the tooltip.
13
+ */
14
+ labelContainer: React.ReactNode;
15
+
16
+ /**
17
+ * Optional width of the tooltip.
18
+ */
19
+ tooltipWidth?: ViewStyle['width'];
20
+
21
+ /**
22
+ * Optional border radius for the tooltip, defined by overlayBorderRadiusType.
23
+ */
24
+ tooltipBorderRadius?: `${overlayBorderRadius}`;
25
+
26
+ /**
27
+ * Optional position of the tooltip, defined by positionType.
28
+ */
29
+ position?: `${positions}`;
30
+
31
+ /**
32
+ * Configuration for styling the tooltip components.
33
+ */
34
+ styleConfig?: {
35
+ /**
36
+ * Styles for the root of the tooltip.
37
+ */
38
+ root?: Styles[];
39
+
40
+ /**
41
+ * Styles for the label container of the tooltip.
42
+ */
43
+ labelContainerStyles?: Styles[];
44
+
45
+ /**
46
+ *
47
+ */
48
+
49
+ arrowStyles?: Styles[];
50
+
51
+ /**
52
+ * Styles for any icons within the tooltip.
53
+ */
54
+ iconStyles?: Styles[];
55
+
56
+ /**
57
+ * Styles for the overlay of the tooltip.
58
+ */
59
+ overlayStyles?: Styles[];
60
+ };
61
+
62
+ /**
63
+ * Indicates whether the tooltip is open or closed.
64
+ */
65
+ open?: boolean;
66
+ /**
67
+ * Indicates whether the tooltip should animate on open/close.
68
+ */
69
+ animate?: boolean;
70
+
71
+ /**
72
+ * Enables hovering over the tooltip container to keep it open.
73
+ */
74
+ enableTooltipContainerHovering?: boolean;
75
+
76
+ /**
77
+ * Ref object for the anchor element.
78
+ */
79
+ anchorRef?: React.RefObject<unknown>;
80
+
81
+ /**
82
+ * Ref object for the tooltip container.
83
+ */
84
+ svgPathProps?: SVGProps<SVGSVGElement>;
85
+ }
86
+
87
+ export interface IDimensionsProps {
88
+ width: number;
89
+ height: number;
90
+ x: number;
91
+ y: number;
92
+ leftEdge?: number;
93
+ rightEdge?: number;
94
+ }
95
+ export interface IMeasurements {
96
+ labelContainer: IDimensionsProps;
97
+ overlayContainer: IDimensionsProps;
98
+ anchorRef: IDimensionsProps;
99
+ }
100
+
101
+ export interface TooltipStyles {
102
+ top?: number;
103
+ left?: number;
104
+ borderRadius?: number;
105
+ }
106
+
107
+ export interface TooltipArrowStyles {
108
+ rotate?: string;
109
+ top?: number;
110
+ left?: number;
111
+ }