@pushwoosh/dumb-components 1.1.154 → 1.1.155
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/Tooltip/Tooltip.d.ts +4 -2
- package/Tooltip/Tooltip.js +85 -39
- package/Tooltip/constants.d.ts +2 -0
- package/Tooltip/constants.js +2 -0
- package/Tooltip/helpers.d.ts +7 -0
- package/Tooltip/helpers.js +21 -0
- package/Tooltip/maps.d.ts +4 -34
- package/Tooltip/maps.js +2 -121
- package/Tooltip/styles.d.ts +3 -4
- package/Tooltip/styles.js +10 -19
- package/Tooltip/types.d.ts +2 -2
- package/Tooltip/useTooltipPosition.d.ts +27 -0
- package/Tooltip/useTooltipPosition.js +63 -0
- package/helpers/assignRef.d.ts +3 -0
- package/helpers/assignRef.js +8 -0
- package/helpers/index.d.ts +1 -0
- package/helpers/index.js +1 -0
- package/package.json +1 -1
package/Tooltip/Tooltip.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import { type ReactElement } from 'react';
|
|
|
2
2
|
import type { TooltipProps } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Wraps an element and shows a contextual tooltip on hover/focus, with configurable
|
|
5
|
-
* position and width.
|
|
5
|
+
* position and width. Positioning is handled by floating-ui, so the tooltip flips to a
|
|
6
|
+
* fallback placement when the requested one would overflow the viewport. Use
|
|
7
|
+
* {@link TooltipTrigger} for a standalone help icon.
|
|
6
8
|
*
|
|
7
9
|
* @example
|
|
8
10
|
* <Tooltip content="Copy to clipboard" position="top-middle"><IconButton /></Tooltip>
|
|
9
11
|
*/
|
|
10
|
-
export declare function Tooltip({
|
|
12
|
+
export declare function Tooltip({ content, position, offset, arrowOffset, maxWidth, zIndex, isDisabled, isVisible, reference, children, }: TooltipProps): ReactElement;
|
package/Tooltip/Tooltip.js
CHANGED
|
@@ -1,53 +1,99 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { cloneElement, isValidElement, useCallback, useEffect, useState } from 'react';
|
|
3
|
+
import { createPortal } from 'react-dom';
|
|
4
|
+
import { assignRef } from '../helpers';
|
|
5
|
+
import { DEFAULT_MAX_WIDTH } from './constants';
|
|
6
|
+
import { Arrow, TooltipBox } from './styles';
|
|
7
|
+
import { useTooltipPosition } from './useTooltipPosition';
|
|
4
8
|
/**
|
|
5
9
|
* Wraps an element and shows a contextual tooltip on hover/focus, with configurable
|
|
6
|
-
* position and width.
|
|
10
|
+
* position and width. Positioning is handled by floating-ui, so the tooltip flips to a
|
|
11
|
+
* fallback placement when the requested one would overflow the viewport. Use
|
|
12
|
+
* {@link TooltipTrigger} for a standalone help icon.
|
|
7
13
|
*
|
|
8
14
|
* @example
|
|
9
15
|
* <Tooltip content="Copy to clipboard" position="top-middle"><IconButton /></Tooltip>
|
|
10
16
|
*/
|
|
11
17
|
export function Tooltip({
|
|
18
|
+
content,
|
|
12
19
|
position = 'top-start',
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
maxWidth =
|
|
20
|
+
offset,
|
|
21
|
+
arrowOffset,
|
|
22
|
+
maxWidth = DEFAULT_MAX_WIDTH,
|
|
16
23
|
zIndex = 999999,
|
|
17
24
|
isDisabled,
|
|
18
25
|
isVisible,
|
|
19
|
-
|
|
26
|
+
reference,
|
|
27
|
+
children
|
|
20
28
|
}) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
placement
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
29
|
+
const isControlled = isVisible !== undefined;
|
|
30
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
31
|
+
const [referenceEl, setReferenceEl] = useState(null);
|
|
32
|
+
const isOpen = !isDisabled && (isControlled ? Boolean(isVisible) : isHovered);
|
|
33
|
+
const {
|
|
34
|
+
refs,
|
|
35
|
+
floatingStyles,
|
|
36
|
+
placement,
|
|
37
|
+
arrowRef,
|
|
38
|
+
arrowStyles
|
|
39
|
+
} = useTooltipPosition({
|
|
40
|
+
position,
|
|
41
|
+
offset,
|
|
42
|
+
arrowOffset,
|
|
43
|
+
maxWidth,
|
|
44
|
+
isOpen
|
|
45
|
+
});
|
|
46
|
+
const {
|
|
47
|
+
setReference
|
|
48
|
+
} = refs;
|
|
49
|
+
const originalRef = isValidElement(children) ? children.ref : undefined;
|
|
50
|
+
const setChildRef = useCallback(node => {
|
|
51
|
+
setReferenceEl(node);
|
|
52
|
+
assignRef(originalRef, node);
|
|
53
|
+
}, [originalRef]);
|
|
54
|
+
const externalReferenceEl = (reference === null || reference === void 0 ? void 0 : reference.current) ?? null;
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (reference) {
|
|
57
|
+
setReferenceEl(externalReferenceEl);
|
|
58
|
+
}
|
|
59
|
+
}, [reference, externalReferenceEl]);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
setReference(referenceEl);
|
|
62
|
+
}, [referenceEl, setReference]);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (isControlled || !referenceEl) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
const show = () => setIsHovered(true);
|
|
68
|
+
const hide = () => setIsHovered(false);
|
|
69
|
+
referenceEl.addEventListener('mouseenter', show);
|
|
70
|
+
referenceEl.addEventListener('mouseleave', hide);
|
|
71
|
+
referenceEl.addEventListener('focusin', show);
|
|
72
|
+
referenceEl.addEventListener('focusout', hide);
|
|
73
|
+
return () => {
|
|
74
|
+
referenceEl.removeEventListener('mouseenter', show);
|
|
75
|
+
referenceEl.removeEventListener('mouseleave', hide);
|
|
76
|
+
referenceEl.removeEventListener('focusin', show);
|
|
77
|
+
referenceEl.removeEventListener('focusout', hide);
|
|
78
|
+
};
|
|
79
|
+
}, [referenceEl, isControlled]);
|
|
80
|
+
const cloneWithRef = cloneElement;
|
|
81
|
+
const anchor = children && isValidElement(children) && !reference ? cloneWithRef(children, {
|
|
82
|
+
ref: setChildRef
|
|
83
|
+
}) : children ?? null;
|
|
84
|
+
return _jsxs(_Fragment, {
|
|
85
|
+
children: [anchor, isOpen && referenceEl && createPortal(_jsxs(TooltipBox, {
|
|
86
|
+
ref: refs.setFloating,
|
|
87
|
+
style: {
|
|
88
|
+
...floatingStyles,
|
|
89
|
+
zIndex
|
|
90
|
+
},
|
|
91
|
+
"$maxWidth": maxWidth,
|
|
92
|
+
"data-placement": placement,
|
|
93
|
+
children: [content, _jsx(Arrow, {
|
|
94
|
+
ref: arrowRef,
|
|
95
|
+
style: arrowStyles
|
|
96
|
+
})]
|
|
97
|
+
}), document.body)]
|
|
52
98
|
});
|
|
53
99
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the legacy `arrowOffset` CSS string into an `arrow()` padding in px — the
|
|
3
|
+
* minimum distance the arrow keeps from the tooltip corners. Accepts `px` values as-is
|
|
4
|
+
* and `%` values relative to the tooltip's max cross size (`maxWidth`, or the default
|
|
5
|
+
* when unbounded), so both forms used with the old tippy tooltip keep working.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseArrowPadding(arrowOffset: string | undefined, maxWidth: number | 'none' | undefined): number;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { DEFAULT_ARROW_PADDING, DEFAULT_MAX_WIDTH } from './constants';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the legacy `arrowOffset` CSS string into an `arrow()` padding in px — the
|
|
4
|
+
* minimum distance the arrow keeps from the tooltip corners. Accepts `px` values as-is
|
|
5
|
+
* and `%` values relative to the tooltip's max cross size (`maxWidth`, or the default
|
|
6
|
+
* when unbounded), so both forms used with the old tippy tooltip keep working.
|
|
7
|
+
*/
|
|
8
|
+
export function parseArrowPadding(arrowOffset, maxWidth) {
|
|
9
|
+
if (!arrowOffset) {
|
|
10
|
+
return DEFAULT_ARROW_PADDING;
|
|
11
|
+
}
|
|
12
|
+
const value = parseFloat(arrowOffset);
|
|
13
|
+
if (Number.isNaN(value)) {
|
|
14
|
+
return DEFAULT_ARROW_PADDING;
|
|
15
|
+
}
|
|
16
|
+
if (arrowOffset.trim().endsWith('%')) {
|
|
17
|
+
const base = typeof maxWidth === 'number' ? maxWidth : DEFAULT_MAX_WIDTH;
|
|
18
|
+
return value / 100 * base;
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
}
|
package/Tooltip/maps.d.ts
CHANGED
|
@@ -1,41 +1,11 @@
|
|
|
1
|
+
import type { Placement } from '@floating-ui/react-dom';
|
|
1
2
|
import type { FC } from 'react';
|
|
2
3
|
import { Color } from '@pushwoosh/kit-constants';
|
|
3
4
|
import { type TooltipTriggerView } from './TooltipTrigger';
|
|
4
5
|
import type { TooltipPosition } from './types';
|
|
5
|
-
export declare const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
'top-end': "top-end";
|
|
9
|
-
'right-start': "right-start";
|
|
10
|
-
'right-middle': "right";
|
|
11
|
-
'right-end': "right-end";
|
|
12
|
-
'bottom-start': "bottom-start";
|
|
13
|
-
'bottom-middle': "bottom";
|
|
14
|
-
'bottom-end': "bottom-end";
|
|
15
|
-
'left-start': "left-start";
|
|
16
|
-
'left-middle': "left";
|
|
17
|
-
'left-end': "left-end";
|
|
18
|
-
};
|
|
19
|
-
export declare const TooltipPositionToTippyOffsetMap: Record<TooltipPosition, [number, number]>;
|
|
20
|
-
export declare const TooltipPositionToArrowOffsetMap: {
|
|
21
|
-
'top-start': string;
|
|
22
|
-
'top-middle': string;
|
|
23
|
-
'top-end': string;
|
|
24
|
-
'right-start': string;
|
|
25
|
-
'right-middle': string;
|
|
26
|
-
'right-end': string;
|
|
27
|
-
'bottom-start': string;
|
|
28
|
-
'bottom-middle': string;
|
|
29
|
-
'bottom-end': string;
|
|
30
|
-
'left-start': string;
|
|
31
|
-
'left-middle': string;
|
|
32
|
-
'left-end': string;
|
|
33
|
-
};
|
|
34
|
-
export declare function getTransform(position: TooltipPosition): "none" | "translateX(-50%) translateY(50%) rotate(45deg);" | "translateX(50%) translateY(50%) rotate(45deg);" | "translateX(-50%) translateY(-50%) rotate(45deg);" | "translateX(50%) translateY(-50%) rotate(45deg);";
|
|
35
|
-
export declare function getTopPosition(position: TooltipPosition, offset: string): string;
|
|
36
|
-
export declare function getRightPosition(position: TooltipPosition, offset: string): string;
|
|
37
|
-
export declare function getBottomPosition(position: TooltipPosition, offset: string): string;
|
|
38
|
-
export declare function getLeftPosition(position: TooltipPosition, offset: string): string;
|
|
6
|
+
export declare const TooltipPositionToFloatingPlacementMap: Record<TooltipPosition, Placement>;
|
|
7
|
+
export declare const TooltipPositionToOffsetMap: Record<TooltipPosition, [number, number]>;
|
|
8
|
+
export declare const TooltipPositionToArrowOffsetMap: Record<TooltipPosition, string>;
|
|
39
9
|
export declare const TooltipTriggerViewMap: Record<TooltipTriggerView, {
|
|
40
10
|
color: Color;
|
|
41
11
|
hoverColor: Color;
|
package/Tooltip/maps.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Color } from '@pushwoosh/kit-constants';
|
|
2
2
|
import { DangerTriangleIcon, HelpRoundIcon, InfoRoundIcon, WarningRoundIcon } from '@pushwoosh/kit-icons';
|
|
3
|
-
export const
|
|
3
|
+
export const TooltipPositionToFloatingPlacementMap = {
|
|
4
4
|
'top-start': 'top-start',
|
|
5
5
|
'top-middle': 'top',
|
|
6
6
|
'top-end': 'top-end',
|
|
@@ -14,7 +14,7 @@ export const TooltipPositionToTippyPlacementMap = {
|
|
|
14
14
|
'left-middle': 'left',
|
|
15
15
|
'left-end': 'left-end'
|
|
16
16
|
};
|
|
17
|
-
export const
|
|
17
|
+
export const TooltipPositionToOffsetMap = {
|
|
18
18
|
'top-start': [-6, 8],
|
|
19
19
|
'top-middle': [0, 8],
|
|
20
20
|
'top-end': [6, 8],
|
|
@@ -42,125 +42,6 @@ export const TooltipPositionToArrowOffsetMap = {
|
|
|
42
42
|
'left-middle': '50%',
|
|
43
43
|
'left-end': '24px'
|
|
44
44
|
};
|
|
45
|
-
export function getTransform(position) {
|
|
46
|
-
switch (position) {
|
|
47
|
-
case 'top-start':
|
|
48
|
-
return 'translateX(-50%) translateY(50%) rotate(45deg);';
|
|
49
|
-
case 'top-middle':
|
|
50
|
-
return 'translateX(-50%) translateY(50%) rotate(45deg);';
|
|
51
|
-
case 'top-end':
|
|
52
|
-
return 'translateX(50%) translateY(50%) rotate(45deg);';
|
|
53
|
-
case 'right-start':
|
|
54
|
-
return 'translateX(-50%) translateY(-50%) rotate(45deg);';
|
|
55
|
-
case 'right-middle':
|
|
56
|
-
return 'translateX(-50%) translateY(-50%) rotate(45deg);';
|
|
57
|
-
case 'right-end':
|
|
58
|
-
return 'translateX(-50%) translateY(50%) rotate(45deg);';
|
|
59
|
-
case 'bottom-start':
|
|
60
|
-
return 'translateX(-50%) translateY(-50%) rotate(45deg);';
|
|
61
|
-
case 'bottom-middle':
|
|
62
|
-
return 'translateX(-50%) translateY(-50%) rotate(45deg);';
|
|
63
|
-
case 'bottom-end':
|
|
64
|
-
return 'translateX(50%) translateY(-50%) rotate(45deg);';
|
|
65
|
-
case 'left-start':
|
|
66
|
-
return 'translateX(50%) translateY(-50%) rotate(45deg);';
|
|
67
|
-
case 'left-middle':
|
|
68
|
-
return 'translateX(50%) translateY(-50%) rotate(45deg);';
|
|
69
|
-
case 'left-end':
|
|
70
|
-
return 'translateX(50%) translateY(50%) rotate(45deg);';
|
|
71
|
-
default:
|
|
72
|
-
console.error(`[Tooltip]: unknown position: ${position}!`);
|
|
73
|
-
return 'none';
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
export function getTopPosition(position, offset) {
|
|
77
|
-
switch (position) {
|
|
78
|
-
case 'top-start':
|
|
79
|
-
case 'top-middle':
|
|
80
|
-
case 'top-end':
|
|
81
|
-
case 'right-end':
|
|
82
|
-
case 'left-end':
|
|
83
|
-
return 'auto';
|
|
84
|
-
case 'right-start':
|
|
85
|
-
case 'right-middle':
|
|
86
|
-
case 'left-start':
|
|
87
|
-
case 'left-middle':
|
|
88
|
-
return offset;
|
|
89
|
-
case 'bottom-start':
|
|
90
|
-
case 'bottom-middle':
|
|
91
|
-
case 'bottom-end':
|
|
92
|
-
return '0';
|
|
93
|
-
default:
|
|
94
|
-
console.error(`[Tooltip]: unknown position: ${position}!`);
|
|
95
|
-
return 'auto';
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
export function getRightPosition(position, offset) {
|
|
99
|
-
switch (position) {
|
|
100
|
-
case 'top-start':
|
|
101
|
-
case 'top-middle':
|
|
102
|
-
case 'right-start':
|
|
103
|
-
case 'right-middle':
|
|
104
|
-
case 'right-end':
|
|
105
|
-
case 'bottom-start':
|
|
106
|
-
case 'bottom-middle':
|
|
107
|
-
return 'auto';
|
|
108
|
-
case 'top-end':
|
|
109
|
-
case 'bottom-end':
|
|
110
|
-
return offset;
|
|
111
|
-
case 'left-end':
|
|
112
|
-
case 'left-start':
|
|
113
|
-
case 'left-middle':
|
|
114
|
-
return '0';
|
|
115
|
-
default:
|
|
116
|
-
console.error(`[Tooltip]: unknown position: ${position}!`);
|
|
117
|
-
return 'auto';
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
export function getBottomPosition(position, offset) {
|
|
121
|
-
switch (position) {
|
|
122
|
-
case 'top-start':
|
|
123
|
-
case 'top-middle':
|
|
124
|
-
case 'top-end':
|
|
125
|
-
return '0';
|
|
126
|
-
case 'right-end':
|
|
127
|
-
case 'left-end':
|
|
128
|
-
return offset;
|
|
129
|
-
case 'bottom-start':
|
|
130
|
-
case 'bottom-middle':
|
|
131
|
-
case 'bottom-end':
|
|
132
|
-
case 'right-start':
|
|
133
|
-
case 'right-middle':
|
|
134
|
-
case 'left-start':
|
|
135
|
-
case 'left-middle':
|
|
136
|
-
return 'auto';
|
|
137
|
-
default:
|
|
138
|
-
console.error(`[Tooltip]: unknown position: ${position}!`);
|
|
139
|
-
return 'auto';
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
export function getLeftPosition(position, offset) {
|
|
143
|
-
switch (position) {
|
|
144
|
-
case 'top-start':
|
|
145
|
-
case 'top-middle':
|
|
146
|
-
case 'bottom-start':
|
|
147
|
-
case 'bottom-middle':
|
|
148
|
-
return offset;
|
|
149
|
-
case 'top-end':
|
|
150
|
-
case 'bottom-end':
|
|
151
|
-
case 'left-end':
|
|
152
|
-
case 'left-start':
|
|
153
|
-
case 'left-middle':
|
|
154
|
-
return 'auto';
|
|
155
|
-
case 'right-start':
|
|
156
|
-
case 'right-end':
|
|
157
|
-
case 'right-middle':
|
|
158
|
-
return '0';
|
|
159
|
-
default:
|
|
160
|
-
console.error(`[Tooltip]: unknown position: ${position}!`);
|
|
161
|
-
return 'auto';
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
45
|
export const TooltipTriggerViewMap = {
|
|
165
46
|
info: {
|
|
166
47
|
color: Color.LOCKED,
|
package/Tooltip/styles.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Color } from '@pushwoosh/kit-constants';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
$arrowOffset: string;
|
|
5
|
-
$position: TooltipPosition;
|
|
2
|
+
export declare const TooltipBox: import("styled-components").StyledComponent<"div", any, {
|
|
3
|
+
$maxWidth?: number | "none";
|
|
6
4
|
}, never>;
|
|
5
|
+
export declare const Arrow: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
7
6
|
export declare const HelpIconWrapper: import("styled-components").StyledComponent<"div", any, import("@pushwoosh/kit-helpers/styled-helpers").CommonBoxProps & {
|
|
8
7
|
$alignContent?: import("@pushwoosh/kit-helpers/styled-helpers").AlignContentValue | undefined;
|
|
9
8
|
$alignItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
|
package/Tooltip/styles.js
CHANGED
|
@@ -1,29 +1,20 @@
|
|
|
1
|
-
import Tippy from '@tippyjs/react';
|
|
2
1
|
import styled from 'styled-components';
|
|
3
2
|
import { Color, FontSize, ShapeRadius } from '@pushwoosh/kit-constants';
|
|
4
3
|
import { Horizontal } from '@pushwoosh/kit-helpers';
|
|
5
|
-
import {
|
|
6
|
-
export const TooltipBox = styled
|
|
4
|
+
import { DEFAULT_MAX_WIDTH } from './constants';
|
|
5
|
+
export const TooltipBox = styled.div.withConfig({
|
|
7
6
|
displayName: "TooltipBox",
|
|
8
7
|
componentId: "sc-1hariht-0"
|
|
9
|
-
})(["
|
|
10
|
-
$
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
})
|
|
16
|
-
$position,
|
|
17
|
-
$arrowOffset
|
|
18
|
-
}) => getBottomPosition($position, $arrowOffset), ({
|
|
19
|
-
$position,
|
|
20
|
-
$arrowOffset
|
|
21
|
-
}) => getLeftPosition($position, $arrowOffset), Color.MAIN, ({
|
|
22
|
-
$position
|
|
23
|
-
}) => getTransform($position), Color.CLEAR, Color.MAIN, ShapeRadius.DIALOG, FontSize.REGULAR);
|
|
8
|
+
})(["padding:12px;color:", ";background-color:", ";border-radius:", ";font-size:", ";line-height:inherit;outline:0;pointer-events:none;max-width:", ";"], Color.CLEAR, Color.MAIN, ShapeRadius.DIALOG, FontSize.REGULAR, ({
|
|
9
|
+
$maxWidth
|
|
10
|
+
}) => $maxWidth === 'none' ? 'min(var(--pw-page-max-width, 100vw), calc(100vw - 16px))' : `min(${$maxWidth ?? DEFAULT_MAX_WIDTH}px, var(--pw-page-max-width, 100vw), calc(100vw - 16px))`);
|
|
11
|
+
export const Arrow = styled.div.withConfig({
|
|
12
|
+
displayName: "Arrow",
|
|
13
|
+
componentId: "sc-1hariht-1"
|
|
14
|
+
})(["position:absolute;width:10px;height:10px;border-radius:2px;background-color:", ";transform:rotate(45deg);"], Color.MAIN);
|
|
24
15
|
export const HelpIconWrapper = styled(Horizontal).withConfig({
|
|
25
16
|
displayName: "HelpIconWrapper",
|
|
26
|
-
componentId: "sc-1hariht-
|
|
17
|
+
componentId: "sc-1hariht-2"
|
|
27
18
|
})(["color:", ";", ""], ({
|
|
28
19
|
$color
|
|
29
20
|
}) => $color, ({
|
package/Tooltip/types.d.ts
CHANGED
|
@@ -7,9 +7,9 @@ export type TooltipProps = {
|
|
|
7
7
|
readonly content: ReactNode;
|
|
8
8
|
/** Placement relative to the anchor (default `top-start`). */
|
|
9
9
|
readonly position?: TooltipPosition;
|
|
10
|
-
/**
|
|
10
|
+
/** `[skidding, distance]` offset from the anchor; defaults per position. */
|
|
11
11
|
readonly offset?: [number, number];
|
|
12
|
-
/**
|
|
12
|
+
/** Min distance the arrow keeps from the tooltip corners — `px` or `%` of `maxWidth`. */
|
|
13
13
|
readonly arrowOffset?: string;
|
|
14
14
|
/** Max width in pixels, or `'none'` (default `240`). */
|
|
15
15
|
readonly maxWidth?: number | 'none';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type CSSProperties } from 'react';
|
|
2
|
+
import type { TooltipPosition } from './types';
|
|
3
|
+
type Args = {
|
|
4
|
+
position: TooltipPosition;
|
|
5
|
+
offset?: [number, number] | undefined;
|
|
6
|
+
arrowOffset?: string | undefined;
|
|
7
|
+
maxWidth?: number | 'none' | undefined;
|
|
8
|
+
isOpen: boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Positions the tooltip relative to its anchor via floating-ui: `flip`/`shift` pick a
|
|
12
|
+
* fallback placement when the requested one overflows the viewport, and `arrow` keeps
|
|
13
|
+
* the arrow pointing at the anchor. Repositions on scroll/resize while open.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useTooltipPosition({ position, offset: offsetProp, arrowOffset, maxWidth, isOpen, }: Args): {
|
|
16
|
+
refs: {
|
|
17
|
+
reference: import("react").MutableRefObject<import("@floating-ui/react-dom").ReferenceType | null>;
|
|
18
|
+
floating: React.MutableRefObject<HTMLElement | null>;
|
|
19
|
+
setReference: (node: import("@floating-ui/react-dom").ReferenceType | null) => void;
|
|
20
|
+
setFloating: (node: HTMLElement | null) => void;
|
|
21
|
+
};
|
|
22
|
+
floatingStyles: CSSProperties;
|
|
23
|
+
placement: import("@floating-ui/utils").Placement;
|
|
24
|
+
arrowRef: import("react").RefObject<HTMLDivElement>;
|
|
25
|
+
arrowStyles: CSSProperties;
|
|
26
|
+
};
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { arrow, autoUpdate, flip, offset, shift, useFloating } from '@floating-ui/react-dom';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import { parseArrowPadding } from './helpers';
|
|
4
|
+
import { TooltipPositionToArrowOffsetMap, TooltipPositionToFloatingPlacementMap, TooltipPositionToOffsetMap } from './maps';
|
|
5
|
+
const ArrowStaticSideMap = {
|
|
6
|
+
top: 'bottom',
|
|
7
|
+
right: 'left',
|
|
8
|
+
bottom: 'top',
|
|
9
|
+
left: 'right'
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Positions the tooltip relative to its anchor via floating-ui: `flip`/`shift` pick a
|
|
13
|
+
* fallback placement when the requested one overflows the viewport, and `arrow` keeps
|
|
14
|
+
* the arrow pointing at the anchor. Repositions on scroll/resize while open.
|
|
15
|
+
*/
|
|
16
|
+
export function useTooltipPosition({
|
|
17
|
+
position,
|
|
18
|
+
offset: offsetProp,
|
|
19
|
+
arrowOffset,
|
|
20
|
+
maxWidth,
|
|
21
|
+
isOpen
|
|
22
|
+
}) {
|
|
23
|
+
const arrowRef = useRef(null);
|
|
24
|
+
const [skidding, distance] = offsetProp ?? TooltipPositionToOffsetMap[position];
|
|
25
|
+
const arrowPadding = parseArrowPadding(arrowOffset ?? TooltipPositionToArrowOffsetMap[position], maxWidth);
|
|
26
|
+
const {
|
|
27
|
+
refs,
|
|
28
|
+
floatingStyles,
|
|
29
|
+
placement,
|
|
30
|
+
middlewareData
|
|
31
|
+
} = useFloating({
|
|
32
|
+
open: isOpen,
|
|
33
|
+
strategy: 'fixed',
|
|
34
|
+
placement: TooltipPositionToFloatingPlacementMap[position],
|
|
35
|
+
middleware: [offset({
|
|
36
|
+
mainAxis: distance,
|
|
37
|
+
crossAxis: skidding
|
|
38
|
+
}), flip(), shift({
|
|
39
|
+
padding: 8
|
|
40
|
+
}), arrow({
|
|
41
|
+
element: arrowRef,
|
|
42
|
+
padding: arrowPadding
|
|
43
|
+
})],
|
|
44
|
+
whileElementsMounted: autoUpdate
|
|
45
|
+
});
|
|
46
|
+
const side = placement.split('-')[0];
|
|
47
|
+
const {
|
|
48
|
+
x: arrowX,
|
|
49
|
+
y: arrowY
|
|
50
|
+
} = middlewareData.arrow ?? {};
|
|
51
|
+
const arrowStyles = {
|
|
52
|
+
left: arrowX != null ? `${arrowX}px` : '',
|
|
53
|
+
top: arrowY != null ? `${arrowY}px` : '',
|
|
54
|
+
[ArrowStaticSideMap[side]]: '-5px'
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
refs,
|
|
58
|
+
floatingStyles,
|
|
59
|
+
placement,
|
|
60
|
+
arrowRef,
|
|
61
|
+
arrowStyles
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './assignRef';
|
package/helpers/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './assignRef';
|