@clayui/tooltip 3.156.0 → 3.158.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.
- package/README.md +4 -4
- package/lib/Tooltip.d.ts +3 -3
- package/lib/TooltipProvider.d.ts +4 -4
- package/lib/cjs/Tooltip.js +67 -30
- package/lib/cjs/TooltipProvider.js +173 -151
- package/lib/cjs/index.js +25 -22
- package/lib/cjs/useAlign.js +84 -58
- package/lib/cjs/useClosestTitle.js +79 -61
- package/lib/cjs/useTooltipState.js +34 -22
- package/lib/esm/Tooltip.js +39 -27
- package/lib/esm/TooltipProvider.js +142 -135
- package/lib/esm/index.js +8 -8
- package/lib/esm/useAlign.js +62 -50
- package/lib/esm/useClosestTitle.js +59 -55
- package/lib/esm/useTooltipState.js +12 -14
- package/lib/index.d.ts +2 -2
- package/lib/useAlign.d.ts +3 -3
- package/lib/useClosestTitle.d.ts +3 -3
- package/lib/useTooltipState.d.ts +2 -2
- package/package.json +33 -34
|
@@ -1,35 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import React, { useCallback, useEffect, useReducer, useRef } from
|
|
8
|
-
import warning from
|
|
9
|
-
import { Tooltip } from "./Tooltip
|
|
10
|
-
import { useAlign } from "./useAlign
|
|
11
|
-
import { useClosestTitle } from "./useClosestTitle
|
|
12
|
-
import { useTooltipState } from "./useTooltipState
|
|
1
|
+
import {
|
|
2
|
+
ClayPortal,
|
|
3
|
+
Keys,
|
|
4
|
+
delegate,
|
|
5
|
+
useInteractionFocus
|
|
6
|
+
} from "@clayui/shared";
|
|
7
|
+
import React, { useCallback, useEffect, useReducer, useRef } from "react";
|
|
8
|
+
import warning from "warning";
|
|
9
|
+
import { Tooltip } from "./Tooltip";
|
|
10
|
+
import { useAlign } from "./useAlign";
|
|
11
|
+
import { useClosestTitle } from "./useClosestTitle";
|
|
12
|
+
import { useTooltipState } from "./useTooltipState";
|
|
13
13
|
const initialState = {
|
|
14
|
-
align:
|
|
14
|
+
align: "top",
|
|
15
15
|
floating: false,
|
|
16
16
|
setAsHTML: false,
|
|
17
|
-
title:
|
|
17
|
+
title: ""
|
|
18
18
|
};
|
|
19
|
-
const TRIGGER_HIDE_EVENTS = [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
const TRIGGER_HIDE_EVENTS = [
|
|
20
|
+
"dragstart",
|
|
21
|
+
"mouseout",
|
|
22
|
+
"mouseup",
|
|
23
|
+
"pointerup",
|
|
24
|
+
"touchend"
|
|
25
|
+
];
|
|
26
|
+
const TRIGGER_SHOW_EVENTS = [
|
|
27
|
+
"mouseover",
|
|
28
|
+
"mouseup",
|
|
29
|
+
"pointerdown",
|
|
30
|
+
"touchstart"
|
|
31
|
+
];
|
|
32
|
+
function reducer(state, { type, ...payload }) {
|
|
26
33
|
switch (type) {
|
|
27
|
-
case
|
|
28
|
-
return {
|
|
29
|
-
|
|
30
|
-
...payload
|
|
31
|
-
};
|
|
32
|
-
case 'reset':
|
|
34
|
+
case "update":
|
|
35
|
+
return { ...state, ...payload };
|
|
36
|
+
case "reset":
|
|
33
37
|
return {
|
|
34
38
|
...state,
|
|
35
39
|
align: initialState.align,
|
|
@@ -38,58 +42,36 @@ const reducer = (state, _ref) => {
|
|
|
38
42
|
default:
|
|
39
43
|
throw new TypeError();
|
|
40
44
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
} =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
setAsHTML,
|
|
55
|
-
title = ''
|
|
56
|
-
}, dispatch] = useReducer(reducer, initialState);
|
|
45
|
+
}
|
|
46
|
+
function ClayTooltipProvider({
|
|
47
|
+
autoAlign = true,
|
|
48
|
+
children,
|
|
49
|
+
containerProps = {},
|
|
50
|
+
contentRenderer = (props) => props.title,
|
|
51
|
+
delay = 600,
|
|
52
|
+
scope
|
|
53
|
+
}) {
|
|
54
|
+
const [{ align, floating, setAsHTML, title = "" }, dispatch] = useReducer(
|
|
55
|
+
reducer,
|
|
56
|
+
initialState
|
|
57
|
+
);
|
|
57
58
|
const tooltipRef = useRef(null);
|
|
58
|
-
const {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
} =
|
|
62
|
-
const
|
|
63
|
-
const isFocused = useRef(false);
|
|
64
|
-
const {
|
|
65
|
-
close,
|
|
66
|
-
isOpen,
|
|
67
|
-
open
|
|
68
|
-
} = useTooltipState({
|
|
69
|
-
delay
|
|
70
|
-
});
|
|
71
|
-
const {
|
|
72
|
-
forceHide,
|
|
73
|
-
getProps,
|
|
74
|
-
onHide,
|
|
75
|
-
target,
|
|
76
|
-
titleNode
|
|
77
|
-
} = useClosestTitle({
|
|
59
|
+
const { getInteraction, isFocusVisible } = useInteractionFocus();
|
|
60
|
+
const isHoveredRef = useRef(false);
|
|
61
|
+
const isFocusedRef = useRef(false);
|
|
62
|
+
const { close, isOpen, open } = useTooltipState({ delay });
|
|
63
|
+
const { forceHide, getProps, onHide, target, titleNode } = useClosestTitle({
|
|
78
64
|
forceHide: useCallback(() => {
|
|
79
|
-
dispatch({
|
|
80
|
-
type: 'reset'
|
|
81
|
-
});
|
|
65
|
+
dispatch({ type: "reset" });
|
|
82
66
|
close();
|
|
83
67
|
}, []),
|
|
84
68
|
onClick: useCallback(() => {
|
|
85
|
-
|
|
86
|
-
|
|
69
|
+
isFocusedRef.current = false;
|
|
70
|
+
isHoveredRef.current = false;
|
|
87
71
|
}, []),
|
|
88
72
|
onHide: useCallback(() => {
|
|
89
|
-
if (!
|
|
90
|
-
dispatch({
|
|
91
|
-
type: 'reset'
|
|
92
|
-
});
|
|
73
|
+
if (!isHoveredRef.current && !isFocusedRef.current) {
|
|
74
|
+
dispatch({ type: "reset" });
|
|
93
75
|
close();
|
|
94
76
|
}
|
|
95
77
|
}, []),
|
|
@@ -100,109 +82,134 @@ export const ClayTooltipProvider = _ref2 => {
|
|
|
100
82
|
autoAlign,
|
|
101
83
|
floating,
|
|
102
84
|
isOpen,
|
|
103
|
-
onAlign: useCallback(
|
|
104
|
-
align,
|
|
105
|
-
type: 'update'
|
|
106
|
-
}), []),
|
|
85
|
+
onAlign: useCallback((align2) => dispatch({ align: align2, type: "update" }), []),
|
|
107
86
|
sourceElement: tooltipRef,
|
|
108
87
|
targetElement: titleNode,
|
|
109
88
|
title
|
|
110
89
|
});
|
|
111
|
-
const onShow = useCallback(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
90
|
+
const onShow = useCallback(
|
|
91
|
+
(event) => {
|
|
92
|
+
if (isHoveredRef.current || isFocusedRef.current) {
|
|
93
|
+
const props = getProps(event, isHoveredRef.current);
|
|
94
|
+
if (props) {
|
|
95
|
+
dispatch({
|
|
96
|
+
align: props.align ?? align,
|
|
97
|
+
floating: props.floating,
|
|
98
|
+
setAsHTML: props.setAsHTML,
|
|
99
|
+
title: props.title,
|
|
100
|
+
type: "update"
|
|
101
|
+
});
|
|
102
|
+
open(
|
|
103
|
+
isFocusedRef.current,
|
|
104
|
+
props.delay ? Number(props.delay) : void 0
|
|
105
|
+
);
|
|
106
|
+
}
|
|
123
107
|
}
|
|
124
|
-
}
|
|
125
|
-
|
|
108
|
+
},
|
|
109
|
+
[align]
|
|
110
|
+
);
|
|
126
111
|
useEffect(() => {
|
|
127
|
-
const handleEsc = event => {
|
|
112
|
+
const handleEsc = (event) => {
|
|
128
113
|
if (isOpen && event.key === Keys.Esc) {
|
|
129
114
|
event.stopImmediatePropagation();
|
|
130
115
|
forceHide();
|
|
131
116
|
}
|
|
132
117
|
};
|
|
133
|
-
document.addEventListener(
|
|
134
|
-
return () => document.removeEventListener(
|
|
118
|
+
document.addEventListener("keyup", handleEsc, true);
|
|
119
|
+
return () => document.removeEventListener("keyup", handleEsc, true);
|
|
135
120
|
}, [isOpen]);
|
|
136
|
-
const onHoverStart = event => {
|
|
137
|
-
if (getInteraction() ===
|
|
138
|
-
|
|
121
|
+
const onHoverStart = (event) => {
|
|
122
|
+
if (getInteraction() === "pointer") {
|
|
123
|
+
isHoveredRef.current = true;
|
|
139
124
|
} else {
|
|
140
|
-
|
|
125
|
+
isHoveredRef.current = false;
|
|
141
126
|
}
|
|
142
127
|
onShow(event);
|
|
143
128
|
};
|
|
144
|
-
const onHoverEnd = event => {
|
|
145
|
-
|
|
146
|
-
|
|
129
|
+
const onHoverEnd = (event) => {
|
|
130
|
+
isFocusedRef.current = false;
|
|
131
|
+
isHoveredRef.current = false;
|
|
147
132
|
onHide(event);
|
|
148
133
|
};
|
|
149
|
-
const onFocus = event => {
|
|
134
|
+
const onFocus = (event) => {
|
|
150
135
|
if (isFocusVisible()) {
|
|
151
|
-
|
|
136
|
+
isFocusedRef.current = true;
|
|
152
137
|
onShow(event);
|
|
153
138
|
}
|
|
154
139
|
};
|
|
155
|
-
const onBlur = event => {
|
|
156
|
-
|
|
157
|
-
|
|
140
|
+
const onBlur = (event) => {
|
|
141
|
+
isFocusedRef.current = false;
|
|
142
|
+
isHoveredRef.current = false;
|
|
158
143
|
onHide(event);
|
|
159
144
|
};
|
|
160
145
|
useEffect(() => {
|
|
161
146
|
if (scope) {
|
|
162
|
-
const disposeShowEvents = TRIGGER_SHOW_EVENTS.map(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
147
|
+
const disposeShowEvents = TRIGGER_SHOW_EVENTS.map(
|
|
148
|
+
(eventName) => delegate(document.body, eventName, scope, onHoverStart)
|
|
149
|
+
);
|
|
150
|
+
const disposeHideEvents = TRIGGER_HIDE_EVENTS.map(
|
|
151
|
+
(eventName) => delegate(
|
|
152
|
+
document.body,
|
|
153
|
+
eventName,
|
|
154
|
+
`${scope}, .tooltip`,
|
|
155
|
+
onHoverEnd
|
|
156
|
+
)
|
|
157
|
+
);
|
|
158
|
+
const disposeShowFocus = delegate(
|
|
159
|
+
document.body,
|
|
160
|
+
"focus",
|
|
161
|
+
`${scope}, .tooltip`,
|
|
162
|
+
onFocus,
|
|
163
|
+
true
|
|
164
|
+
);
|
|
165
|
+
const disposeCloseBlur = delegate(
|
|
166
|
+
document.body,
|
|
167
|
+
"blur",
|
|
168
|
+
`${scope}, .tooltip`,
|
|
169
|
+
onBlur,
|
|
170
|
+
true
|
|
171
|
+
);
|
|
166
172
|
return () => {
|
|
167
|
-
disposeShowEvents.forEach(
|
|
168
|
-
|
|
169
|
-
dispose
|
|
170
|
-
} = _ref3;
|
|
171
|
-
return dispose();
|
|
172
|
-
});
|
|
173
|
-
disposeHideEvents.forEach(_ref4 => {
|
|
174
|
-
let {
|
|
175
|
-
dispose
|
|
176
|
-
} = _ref4;
|
|
177
|
-
return dispose();
|
|
178
|
-
});
|
|
173
|
+
disposeShowEvents.forEach(({ dispose }) => dispose());
|
|
174
|
+
disposeHideEvents.forEach(({ dispose }) => dispose());
|
|
179
175
|
disposeShowFocus.dispose();
|
|
180
176
|
disposeCloseBlur.dispose();
|
|
181
177
|
};
|
|
182
178
|
}
|
|
183
179
|
}, [onShow]);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
180
|
+
warning(
|
|
181
|
+
typeof children === "undefined" && typeof scope !== "undefined" || typeof scope === "undefined" && typeof children !== "undefined",
|
|
182
|
+
"<TooltipProvider />: You must use at least one of the following props: `children` or `scope`."
|
|
183
|
+
);
|
|
184
|
+
warning(
|
|
185
|
+
typeof children !== "undefined" || typeof scope !== "undefined",
|
|
186
|
+
"<TooltipProvider />: If you want to use `scope`, use <TooltipProvider /> as a singleton and do not pass `children`."
|
|
187
|
+
);
|
|
188
|
+
warning(
|
|
189
|
+
children?.type !== React.Fragment,
|
|
190
|
+
"<TooltipProvider />: React Fragment is not allowed as a child to TooltipProvider. Child must be a single HTML element that accepts `onMouseOver` and `onMouseOut`."
|
|
191
|
+
);
|
|
187
192
|
const titleContent = contentRenderer({
|
|
188
193
|
targetNode: target.current,
|
|
189
194
|
title
|
|
190
195
|
});
|
|
191
|
-
const tooltip = isOpen &&
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
__html: titleContent
|
|
196
|
+
const tooltip = isOpen && /* @__PURE__ */ React.createElement(ClayPortal, { ...containerProps }, /* @__PURE__ */ React.createElement(Tooltip, { alignPosition: align, ref: tooltipRef, show: true }, setAsHTML && typeof titleContent === "string" ? /* @__PURE__ */ React.createElement(
|
|
197
|
+
"span",
|
|
198
|
+
{
|
|
199
|
+
dangerouslySetInnerHTML: {
|
|
200
|
+
__html: titleContent
|
|
201
|
+
}
|
|
198
202
|
}
|
|
199
|
-
|
|
200
|
-
return
|
|
203
|
+
) : titleContent));
|
|
204
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, scope ? /* @__PURE__ */ React.createElement(React.Fragment, null, tooltip, children) : children && React.cloneElement(children, {
|
|
201
205
|
...children.props,
|
|
202
|
-
children:
|
|
206
|
+
children: /* @__PURE__ */ React.createElement(React.Fragment, null, children.props.children, tooltip),
|
|
203
207
|
onBlur,
|
|
204
208
|
onFocus,
|
|
205
209
|
onMouseOut: onHoverEnd,
|
|
206
210
|
onMouseOver: onHoverStart
|
|
207
211
|
}));
|
|
208
|
-
}
|
|
212
|
+
}
|
|
213
|
+
export {
|
|
214
|
+
ClayTooltipProvider
|
|
215
|
+
};
|
package/lib/esm/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { Tooltip } from "./Tooltip";
|
|
2
|
+
import { ClayTooltipProvider } from "./TooltipProvider";
|
|
3
|
+
var src_default = Tooltip;
|
|
4
|
+
export {
|
|
5
|
+
ClayTooltipProvider,
|
|
6
|
+
Tooltip,
|
|
7
|
+
src_default as default
|
|
8
|
+
};
|
package/lib/esm/useAlign.js
CHANGED
|
@@ -1,31 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { doAlign, useMousePosition } from "@clayui/shared";
|
|
2
|
+
import { alignPoint } from "dom-align";
|
|
3
|
+
import { useEffect } from "react";
|
|
4
|
+
const ALIGNMENTS = [
|
|
5
|
+
"top",
|
|
6
|
+
"top-right",
|
|
7
|
+
"right",
|
|
8
|
+
"bottom-right",
|
|
9
|
+
"bottom",
|
|
10
|
+
"bottom-left",
|
|
11
|
+
"left",
|
|
12
|
+
"top-left"
|
|
13
|
+
];
|
|
10
14
|
const ALIGNMENTS_MAP = {
|
|
11
|
-
bottom: [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
left: [
|
|
15
|
-
right: [
|
|
16
|
-
top: [
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
"bottom": ["tc", "bc"],
|
|
16
|
+
"bottom-left": ["tl", "bl"],
|
|
17
|
+
"bottom-right": ["tr", "br"],
|
|
18
|
+
"left": ["cr", "cl"],
|
|
19
|
+
"right": ["cl", "cr"],
|
|
20
|
+
"top": ["bc", "tc"],
|
|
21
|
+
"top-left": ["bl", "tl"],
|
|
22
|
+
"top-right": ["br", "tr"]
|
|
19
23
|
};
|
|
20
24
|
const ALIGNMENTS_INVERSE_MAP = {
|
|
21
|
-
bctc:
|
|
22
|
-
bltl:
|
|
23
|
-
brtr:
|
|
24
|
-
clcr:
|
|
25
|
-
crcl:
|
|
26
|
-
tcbc:
|
|
27
|
-
tlbl:
|
|
28
|
-
trbr:
|
|
25
|
+
bctc: "top",
|
|
26
|
+
bltl: "top-left",
|
|
27
|
+
brtr: "top-right",
|
|
28
|
+
clcr: "right",
|
|
29
|
+
crcl: "left",
|
|
30
|
+
tcbc: "bottom",
|
|
31
|
+
tlbl: "bottom-left",
|
|
32
|
+
trbr: "bottom-right"
|
|
29
33
|
};
|
|
30
34
|
const BOTTOM_OFFSET = [0, 7];
|
|
31
35
|
const LEFT_OFFSET = [-7, 0];
|
|
@@ -43,37 +47,40 @@ const OFFSET_MAP = {
|
|
|
43
47
|
};
|
|
44
48
|
const ALIGNMENTS_FORCE_MAP = {
|
|
45
49
|
...ALIGNMENTS_INVERSE_MAP,
|
|
46
|
-
bctc:
|
|
47
|
-
tcbc:
|
|
50
|
+
bctc: "top-left",
|
|
51
|
+
tcbc: "bottom-left"
|
|
48
52
|
};
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
} = _ref;
|
|
53
|
+
function useAlign({
|
|
54
|
+
align,
|
|
55
|
+
autoAlign,
|
|
56
|
+
floating,
|
|
57
|
+
isOpen,
|
|
58
|
+
onAlign,
|
|
59
|
+
sourceElement,
|
|
60
|
+
targetElement,
|
|
61
|
+
title
|
|
62
|
+
}) {
|
|
60
63
|
const mousePosition = useMousePosition(20);
|
|
61
64
|
useEffect(() => {
|
|
62
65
|
if (sourceElement.current && isOpen && floating) {
|
|
63
|
-
const points = ALIGNMENTS_MAP[align ||
|
|
66
|
+
const points = ALIGNMENTS_MAP[align || "top"];
|
|
64
67
|
const [clientX, clientY] = mousePosition;
|
|
65
|
-
alignPoint(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
alignPoint(
|
|
69
|
+
sourceElement.current,
|
|
70
|
+
{
|
|
71
|
+
clientX,
|
|
72
|
+
clientY
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
offset: OFFSET_MAP[points.join("")],
|
|
76
|
+
points
|
|
77
|
+
}
|
|
78
|
+
);
|
|
72
79
|
}
|
|
73
80
|
}, [isOpen, floating]);
|
|
74
81
|
useEffect(() => {
|
|
75
82
|
if (targetElement.current && sourceElement.current && isOpen && !floating) {
|
|
76
|
-
const points = ALIGNMENTS_MAP[align ||
|
|
83
|
+
const points = ALIGNMENTS_MAP[align || "top"];
|
|
77
84
|
const alignment = doAlign({
|
|
78
85
|
overflow: {
|
|
79
86
|
adjustX: autoAlign,
|
|
@@ -83,8 +90,10 @@ export function useAlign(_ref) {
|
|
|
83
90
|
sourceElement: sourceElement.current,
|
|
84
91
|
targetElement: targetElement.current
|
|
85
92
|
});
|
|
86
|
-
const alignmentString = alignment.points.join(
|
|
87
|
-
|
|
93
|
+
const alignmentString = alignment.points.join(
|
|
94
|
+
""
|
|
95
|
+
);
|
|
96
|
+
const pointsString = points.join("");
|
|
88
97
|
if (alignment.overflow.adjustX) {
|
|
89
98
|
onAlign(ALIGNMENTS_FORCE_MAP[alignmentString]);
|
|
90
99
|
} else if (pointsString !== alignmentString) {
|
|
@@ -92,4 +101,7 @@ export function useAlign(_ref) {
|
|
|
92
101
|
}
|
|
93
102
|
}
|
|
94
103
|
}, [align, title, isOpen]);
|
|
95
|
-
}
|
|
104
|
+
}
|
|
105
|
+
export {
|
|
106
|
+
useAlign
|
|
107
|
+
};
|