@rescui/tooltip 0.12.1 → 0.12.3-RUI-308-Fix-select-issues-405b9fa40.12
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/lib/index.css +30 -23
- package/lib/tooltip.js +53 -88
- package/lib/tooltip.p.module.css.js +7 -7
- package/lib/use-tooltip-state.d.ts +10 -1
- package/lib/use-tooltip-state.js +112 -17
- package/package.json +7 -6
package/lib/index.css
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
@property --_rs-theme-dark-coefficient{
|
|
2
|
+
syntax:'<number>';
|
|
3
|
+
inherits:true;
|
|
4
|
+
initial-value:0;
|
|
5
|
+
}
|
|
6
|
+
._tooltip_1o1u5fj_5{
|
|
2
7
|
position:relative;
|
|
3
8
|
}
|
|
4
|
-
.
|
|
9
|
+
._closing_1o1u5fj_9{
|
|
5
10
|
pointer-events:none;
|
|
6
11
|
}
|
|
7
|
-
.
|
|
12
|
+
._content_1o1u5fj_13{
|
|
8
13
|
--rs-theme-dark:1;
|
|
9
14
|
--_rs-tooltip-border-width:1px;
|
|
10
15
|
|
|
@@ -63,6 +68,8 @@
|
|
|
63
68
|
--_rs-typography-link-external-standalone-border-offset-from-text-base:1.02em;
|
|
64
69
|
--_rs-typography-link-border-bottom-width-from-text:1px;
|
|
65
70
|
|
|
71
|
+
color-scheme:dark;
|
|
72
|
+
|
|
66
73
|
max-width:283px;
|
|
67
74
|
|
|
68
75
|
padding:calc(8px - var(--_rs-tooltip-border-width));
|
|
@@ -76,33 +83,33 @@
|
|
|
76
83
|
transition:opacity 300ms var(--rs-transition-function, ease), transform 300ms var(--rs-transition-function, ease);
|
|
77
84
|
transform:translate(0, 0);
|
|
78
85
|
}
|
|
79
|
-
[data-popper-placement='top-end'] .
|
|
80
|
-
[data-popper-placement='bottom-end'] .
|
|
86
|
+
[data-popper-placement='top-end'] ._content_1o1u5fj_13,
|
|
87
|
+
[data-popper-placement='bottom-end'] ._content_1o1u5fj_13{
|
|
81
88
|
margin-right:0;
|
|
82
89
|
}
|
|
83
|
-
[data-popper-placement='top-start'] .
|
|
84
|
-
[data-popper-placement='bottom-start'] .
|
|
90
|
+
[data-popper-placement='top-start'] ._content_1o1u5fj_13,
|
|
91
|
+
[data-popper-placement='bottom-start'] ._content_1o1u5fj_13{
|
|
85
92
|
margin-left:0;
|
|
86
93
|
}
|
|
87
|
-
[data-popper-placement='left-end'] .
|
|
88
|
-
[data-popper-placement='right-end'] .
|
|
94
|
+
[data-popper-placement='left-end'] ._content_1o1u5fj_13,
|
|
95
|
+
[data-popper-placement='right-end'] ._content_1o1u5fj_13{
|
|
89
96
|
margin-bottom:0;
|
|
90
97
|
}
|
|
91
|
-
[data-popper-placement='left-start'] .
|
|
92
|
-
[data-popper-placement='right-start'] .
|
|
98
|
+
[data-popper-placement='left-start'] ._content_1o1u5fj_13,
|
|
99
|
+
[data-popper-placement='right-start'] ._content_1o1u5fj_13{
|
|
93
100
|
margin-top:0;
|
|
94
101
|
}
|
|
95
|
-
.
|
|
102
|
+
._initial_1o1u5fj_57 ._content_1o1u5fj_13{
|
|
96
103
|
transition:none;
|
|
97
104
|
}
|
|
98
|
-
.
|
|
105
|
+
._closing_1o1u5fj_9 ._content_1o1u5fj_13{
|
|
99
106
|
transition-duration:200ms, 200ms;
|
|
100
107
|
}
|
|
101
|
-
.
|
|
102
|
-
.
|
|
108
|
+
._initial_1o1u5fj_57 ._content_1o1u5fj_13,
|
|
109
|
+
._closing_1o1u5fj_9 ._content_1o1u5fj_13{
|
|
103
110
|
opacity:0;
|
|
104
111
|
}
|
|
105
|
-
.
|
|
112
|
+
._outerThemeLight_1o1u5fj_71 ._content_1o1u5fj_13{
|
|
106
113
|
--rs-color-primary-dark-theme:var(--rs-color-primary-light-theme);
|
|
107
114
|
--rs-color-primary-dim-dark-theme:var(--rs-color-primary-dim-light-theme);
|
|
108
115
|
--rs-color-primary-fog-dark-theme:var(--rs-color-primary-fog-light-theme);
|
|
@@ -113,7 +120,7 @@
|
|
|
113
120
|
--rs-color-primary-t-fog-light-theme
|
|
114
121
|
);
|
|
115
122
|
}
|
|
116
|
-
.
|
|
123
|
+
._outerThemeDark_1o1u5fj_84 ._content_1o1u5fj_13{
|
|
117
124
|
--rs-color-primary-light-theme:var(--rs-color-primary-dark-theme);
|
|
118
125
|
--rs-color-primary-dim-light-theme:var(--rs-color-primary-dim-dark-theme);
|
|
119
126
|
--rs-color-primary-fog-light-theme:var(--rs-color-primary-fog-dark-theme);
|
|
@@ -124,20 +131,20 @@
|
|
|
124
131
|
--rs-color-primary-t-fog-dark-theme
|
|
125
132
|
);
|
|
126
133
|
}
|
|
127
|
-
.
|
|
134
|
+
._initial_1o1u5fj_57[data-popper-placement^='top'] ._content_1o1u5fj_13, ._closing_1o1u5fj_9[data-popper-placement^='top'] ._content_1o1u5fj_13{
|
|
128
135
|
transform:translate(0, 10px);
|
|
129
136
|
}
|
|
130
|
-
.
|
|
137
|
+
._initial_1o1u5fj_57[data-popper-placement^='right'] ._content_1o1u5fj_13, ._closing_1o1u5fj_9[data-popper-placement^='right'] ._content_1o1u5fj_13{
|
|
131
138
|
transform:translate(-10px, 0);
|
|
132
139
|
}
|
|
133
|
-
.
|
|
140
|
+
._initial_1o1u5fj_57[data-popper-placement^='bottom'] ._content_1o1u5fj_13, ._closing_1o1u5fj_9[data-popper-placement^='bottom'] ._content_1o1u5fj_13{
|
|
134
141
|
transform:translate(0, -10px);
|
|
135
142
|
}
|
|
136
|
-
.
|
|
143
|
+
._initial_1o1u5fj_57[data-popper-placement^='left'] ._content_1o1u5fj_13, ._closing_1o1u5fj_9[data-popper-placement^='left'] ._content_1o1u5fj_13{
|
|
137
144
|
transform:translate(10px, 0);
|
|
138
145
|
}
|
|
139
|
-
.
|
|
140
|
-
.
|
|
146
|
+
._trigger_1o1u5fj_116:focus-visible,
|
|
147
|
+
._trigger_1o1u5fj_116:focus[data-focus-method='key']{
|
|
141
148
|
outline:none;
|
|
142
149
|
|
|
143
150
|
box-shadow:var(--rs-color-primary-t-dim-light-theme) 0 0 0 4px;
|
package/lib/tooltip.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
|
|
3
|
-
import React, { cloneElement, createElement, useState, useRef,
|
|
3
|
+
import React, { cloneElement, createElement, useState, useRef, useCallback, useContext, isValidElement } from 'react';
|
|
4
4
|
import cn from 'classnames';
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import ReactDOM from 'react-dom';
|
|
7
7
|
import { usePopper } from 'react-popper';
|
|
8
8
|
import { useLayeringContext, ThemeContext, ThemeProvider } from '@rescui/ui-contexts';
|
|
9
|
+
import { useResizeObserver } from '@rescui/use-resize-observer';
|
|
9
10
|
import styles from './tooltip.p.module.css.js';
|
|
10
11
|
import { useTooltipState, TOOLTIP_STATES } from './use-tooltip-state.js';
|
|
11
12
|
import { extractThemeFromCss, extractPrimaryColors } from './css-vars-utils.js';
|
|
@@ -137,30 +138,21 @@ const Tooltip = _ref4 => {
|
|
|
137
138
|
tooltipZIndex
|
|
138
139
|
} = useLayeringContext();
|
|
139
140
|
const [popperRef, setPopperRef] = useState(null);
|
|
140
|
-
const [triggerRef, setTriggerRef] = useState(
|
|
141
|
+
const [triggerRef, setTriggerRef] = useState(undefined);
|
|
141
142
|
const [isVisibleState, setIsVisibleState] = useState(false);
|
|
142
143
|
const [isTooltipHovered, setIsTooltipHovered] = useState(false);
|
|
143
|
-
const
|
|
144
|
-
const contentRef = useRef(null);
|
|
144
|
+
const [contentEl, setContentEl] = useState(null);
|
|
145
145
|
const hideTimeoutRef = useRef(null);
|
|
146
146
|
const isControlled = typeof isVisibleFromProps !== 'undefined';
|
|
147
|
-
|
|
148
|
-
// the
|
|
149
|
-
// So even if isVisible prop is used, the tooltip will not render on the server, and
|
|
150
|
-
// it's the same on the first client render, so there is no hydration issue.
|
|
147
|
+
const requestedVisibility = isControlled ? isVisibleFromProps : isVisibleState; // An undefined ref means that React has not committed the trigger yet. It keeps
|
|
148
|
+
// the server and first client render equal without an extra hydration state.
|
|
151
149
|
|
|
152
|
-
const
|
|
153
|
-
useEffect(() => {
|
|
154
|
-
setIsFirstRender(false);
|
|
155
|
-
}, []);
|
|
156
|
-
isVisible = isFirstRender && !renderBesideTrigger ? false : isVisible;
|
|
150
|
+
const isVisible = typeof triggerRef !== 'undefined' || renderBesideTrigger ? requestedVisibility : false;
|
|
157
151
|
const ownerDocument = triggerRef?.ownerDocument;
|
|
158
152
|
const isOpen = isVisible || isTooltipHovered;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
}, [content]);
|
|
153
|
+
const contentCanBeRendered = isNode(content);
|
|
154
|
+
const portalTargetIsAvailable = renderBesideTrigger || Boolean(ownerDocument?.body);
|
|
155
|
+
const canRenderTooltip = contentCanBeRendered && portalTargetIsAvailable;
|
|
164
156
|
|
|
165
157
|
const handleMouseEnterTarget = () => {
|
|
166
158
|
if (hideTimeoutRef.current) {
|
|
@@ -181,66 +173,10 @@ const Tooltip = _ref4 => {
|
|
|
181
173
|
}
|
|
182
174
|
};
|
|
183
175
|
|
|
184
|
-
const
|
|
185
|
-
const isClosing = tooltipState === TOOLTIP_STATES.CLOSING;
|
|
186
|
-
const isExists = tooltipState !== TOOLTIP_STATES.CLOSE; // a state to toggle the starting transition
|
|
187
|
-
|
|
188
|
-
const [isInitial, setIsInitial] = useState(true); // reset the initial flag when the closing transition ends and the state switches to CLOSED
|
|
189
|
-
|
|
190
|
-
useEffect(() => {
|
|
191
|
-
if (!isExists) {
|
|
192
|
-
setIsInitial(true);
|
|
193
|
-
}
|
|
194
|
-
}, [isExists]);
|
|
195
|
-
const disableInitialFlag = useCallback(_ref5 => {
|
|
196
|
-
let {
|
|
197
|
-
state
|
|
198
|
-
} = _ref5;
|
|
199
|
-
const el = state.elements.popper; // force layout phase
|
|
200
|
-
// to make sure that the dom has registered the initial
|
|
201
|
-
// styles with resolved placement (for `auto` placement)
|
|
202
|
-
|
|
203
|
-
el.getBoundingClientRect();
|
|
204
|
-
setIsInitial(false);
|
|
205
|
-
}, []);
|
|
206
|
-
const tooltipShouldBeRendered = isExists && isNode(content); // immediately fire handleAnimationEnd event on visibility change in case transition is disabled
|
|
207
|
-
// it may happen if the user hard-disabled all transitions in his browser
|
|
208
|
-
|
|
209
|
-
useEffect(() => {
|
|
210
|
-
if (!isInitial && contentRef.current) {
|
|
211
|
-
const ownerWindow = contentRef.current.ownerDocument.defaultView;
|
|
212
|
-
const isTransitionDisabled = ownerWindow?.getComputedStyle(contentRef.current).transitionDuration === '0s';
|
|
213
|
-
|
|
214
|
-
if (isTransitionDisabled) {
|
|
215
|
-
handleAnimationEnd();
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}, [handleAnimationEnd, isInitial]);
|
|
219
|
-
let primaryColors = {};
|
|
220
|
-
let themeFromCss = 'light';
|
|
221
|
-
|
|
222
|
-
if (triggerRef && tooltipShouldBeRendered) {
|
|
223
|
-
// In theory this part of the code might cause issues with SSR.
|
|
224
|
-
// But in this specific context, because of the nature of the state-ref "triggerRef",
|
|
225
|
-
// we are sure that the tooltip wouldn't be rendered on the first client render.
|
|
226
|
-
// Therefore, the first render on the client will be the same as on the server.
|
|
227
|
-
const triggerStyles = ownerDocument?.defaultView?.getComputedStyle(triggerRef);
|
|
228
|
-
|
|
229
|
-
if (triggerStyles) {
|
|
230
|
-
themeFromCss = extractThemeFromCss(triggerStyles);
|
|
231
|
-
primaryColors = extractPrimaryColors(triggerStyles);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const {
|
|
236
|
-
theme: themeFromContext,
|
|
237
|
-
noProvider
|
|
238
|
-
} = useContext(ThemeContext);
|
|
239
|
-
const theme = noProvider ? themeFromCss : themeFromContext;
|
|
240
|
-
const calcOffset = useCallback(_ref6 => {
|
|
176
|
+
const calcOffset = useCallback(_ref5 => {
|
|
241
177
|
let {
|
|
242
178
|
placement: offsetPlacement
|
|
243
|
-
} =
|
|
179
|
+
} = _ref5;
|
|
244
180
|
|
|
245
181
|
if (_includesInstanceProperty(offsetPlacement).call(offsetPlacement, 'left') || _includesInstanceProperty(offsetPlacement).call(offsetPlacement, 'right')) {
|
|
246
182
|
return [0, sparse ? 16 : 8];
|
|
@@ -252,16 +188,9 @@ const Tooltip = _ref4 => {
|
|
|
252
188
|
styles: popperStyles,
|
|
253
189
|
attributes,
|
|
254
190
|
update
|
|
255
|
-
} = usePopper(triggerRef, popperRef, {
|
|
191
|
+
} = usePopper(triggerRef ?? null, popperRef, {
|
|
256
192
|
placement,
|
|
257
|
-
modifiers: [
|
|
258
|
-
{
|
|
259
|
-
name: 'disableInitialFlag',
|
|
260
|
-
enabled: true,
|
|
261
|
-
phase: 'afterWrite',
|
|
262
|
-
fn: disableInitialFlag,
|
|
263
|
-
requires: []
|
|
264
|
-
}, {
|
|
193
|
+
modifiers: [{
|
|
265
194
|
name: 'flip',
|
|
266
195
|
options: {
|
|
267
196
|
fallbackPlacements
|
|
@@ -273,7 +202,44 @@ const Tooltip = _ref4 => {
|
|
|
273
202
|
}
|
|
274
203
|
}, ...(modifiers || [])]
|
|
275
204
|
});
|
|
276
|
-
|
|
205
|
+
useResizeObserver(contentEl, () => {
|
|
206
|
+
update?.();
|
|
207
|
+
}, {
|
|
208
|
+
ignoreFirstCall: true
|
|
209
|
+
});
|
|
210
|
+
const resolvedPlacement = attributes.popper?.['data-popper-placement'] ?? null;
|
|
211
|
+
const tooltipState = useTooltipState({
|
|
212
|
+
isOpen,
|
|
213
|
+
canRender: canRenderTooltip,
|
|
214
|
+
contentEl,
|
|
215
|
+
popperElement: popperRef,
|
|
216
|
+
resolvedPlacement
|
|
217
|
+
});
|
|
218
|
+
const isInitial = tooltipState === TOOLTIP_STATES.OPENING_PREPARE;
|
|
219
|
+
const isClosing = tooltipState === TOOLTIP_STATES.CLOSING;
|
|
220
|
+
const isExists = tooltipState !== TOOLTIP_STATES.CLOSE;
|
|
221
|
+
const tooltipShouldBeRendered = isExists && canRenderTooltip;
|
|
222
|
+
let primaryColors = {};
|
|
223
|
+
let themeFromCss = 'light';
|
|
224
|
+
|
|
225
|
+
if (triggerRef && tooltipShouldBeRendered) {
|
|
226
|
+
// In theory this part of the code might cause issues with SSR.
|
|
227
|
+
// But in this specific context, because of the nature of the state-ref "triggerRef",
|
|
228
|
+
// we are sure that the tooltip wouldn't be rendered on the first client render.
|
|
229
|
+
// Therefore, the first render on the client will be the same as on the server.
|
|
230
|
+
const triggerStyles = ownerDocument?.defaultView?.getComputedStyle(triggerRef);
|
|
231
|
+
|
|
232
|
+
if (triggerStyles) {
|
|
233
|
+
themeFromCss = extractThemeFromCss(triggerStyles);
|
|
234
|
+
primaryColors = extractPrimaryColors(triggerStyles);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const {
|
|
239
|
+
theme: themeFromContext,
|
|
240
|
+
noProvider
|
|
241
|
+
} = useContext(ThemeContext);
|
|
242
|
+
const theme = noProvider ? themeFromCss : themeFromContext;
|
|
277
243
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TriggerRenderer, {
|
|
278
244
|
setTriggerRef: setTriggerRef,
|
|
279
245
|
targetComponent: targetComponent,
|
|
@@ -312,8 +278,7 @@ const Tooltip = _ref4 => {
|
|
|
312
278
|
className: cn(styles.content),
|
|
313
279
|
onBlur: handleMouseLeaveTarget,
|
|
314
280
|
onFocus: handleMouseEnterTarget,
|
|
315
|
-
|
|
316
|
-
ref: contentRef
|
|
281
|
+
ref: setContentEl
|
|
317
282
|
}, content)))));
|
|
318
283
|
};
|
|
319
284
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
var styles = {
|
|
2
|
-
"tooltip": "
|
|
3
|
-
"closing": "
|
|
4
|
-
"content": "
|
|
5
|
-
"initial": "
|
|
6
|
-
"outerThemeLight": "
|
|
7
|
-
"outerThemeDark": "
|
|
8
|
-
"trigger": "
|
|
2
|
+
"tooltip": "_tooltip_1o1u5fj_5",
|
|
3
|
+
"closing": "_closing_1o1u5fj_9",
|
|
4
|
+
"content": "_content_1o1u5fj_13",
|
|
5
|
+
"initial": "_initial_1o1u5fj_57",
|
|
6
|
+
"outerThemeLight": "_outerThemeLight_1o1u5fj_71",
|
|
7
|
+
"outerThemeDark": "_outerThemeDark_1o1u5fj_84",
|
|
8
|
+
"trigger": "_trigger_1o1u5fj_116"
|
|
9
9
|
};
|
|
10
10
|
export { styles as default };
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
export declare enum TOOLTIP_STATES {
|
|
2
|
+
OPENING_PREPARE = "OPENING_PREPARE",
|
|
2
3
|
OPENING = "OPENING",
|
|
3
4
|
OPEN = "OPEN",
|
|
4
5
|
CLOSING = "CLOSING",
|
|
5
6
|
CLOSE = "CLOSE"
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
+
type UseTooltipStateOptions = {
|
|
9
|
+
isOpen: boolean;
|
|
10
|
+
canRender?: boolean;
|
|
11
|
+
contentEl: HTMLDivElement | null;
|
|
12
|
+
popperElement: HTMLElement | null;
|
|
13
|
+
resolvedPlacement: string | null;
|
|
14
|
+
};
|
|
15
|
+
export declare function useTooltipState({ isOpen, canRender, contentEl, popperElement, resolvedPlacement }: UseTooltipStateOptions): TOOLTIP_STATES;
|
|
16
|
+
export {};
|
package/lib/use-tooltip-state.js
CHANGED
|
@@ -1,36 +1,131 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useState,
|
|
2
|
+
import { useState, useCallback, useEffect, useLayoutEffect } from 'react';
|
|
3
|
+
const useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;
|
|
4
|
+
const TOOLTIP_TRANSITION_PROPERTIES = ['opacity', 'transform'];
|
|
5
|
+
|
|
6
|
+
const getTooltipTransition = (element, property) => element.getAnimations().find(animation => animation.transitionProperty === property);
|
|
7
|
+
|
|
3
8
|
var TOOLTIP_STATES;
|
|
4
9
|
|
|
5
10
|
(function (TOOLTIP_STATES) {
|
|
11
|
+
TOOLTIP_STATES["OPENING_PREPARE"] = "OPENING_PREPARE";
|
|
6
12
|
TOOLTIP_STATES["OPENING"] = "OPENING";
|
|
7
13
|
TOOLTIP_STATES["OPEN"] = "OPEN";
|
|
8
14
|
TOOLTIP_STATES["CLOSING"] = "CLOSING";
|
|
9
15
|
TOOLTIP_STATES["CLOSE"] = "CLOSE";
|
|
10
16
|
})(TOOLTIP_STATES || (TOOLTIP_STATES = {}));
|
|
11
17
|
|
|
12
|
-
function useTooltipState(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
function useTooltipState(_ref) {
|
|
19
|
+
let {
|
|
20
|
+
isOpen,
|
|
21
|
+
canRender = true,
|
|
22
|
+
contentEl,
|
|
23
|
+
popperElement,
|
|
24
|
+
resolvedPlacement
|
|
25
|
+
} = _ref;
|
|
26
|
+
const [tooltipState, setTooltipState] = useState(isOpen && canRender ? TOOLTIP_STATES.OPENING_PREPARE : TOOLTIP_STATES.CLOSE);
|
|
27
|
+
const completeTransition = useCallback(expectedState => {
|
|
28
|
+
setTooltipState(state => {
|
|
29
|
+
if (state !== expectedState) {
|
|
30
|
+
return state;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (expectedState === TOOLTIP_STATES.CLOSING) {
|
|
34
|
+
return TOOLTIP_STATES.CLOSE;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (expectedState === TOOLTIP_STATES.OPENING) {
|
|
38
|
+
return TOOLTIP_STATES.OPEN;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return state;
|
|
42
|
+
});
|
|
43
|
+
}, []);
|
|
44
|
+
const completeOpeningPreparation = useCallback(() => {
|
|
45
|
+
setTooltipState(state => state === TOOLTIP_STATES.OPENING_PREPARE ? TOOLTIP_STATES.OPENING : state);
|
|
46
|
+
}, []);
|
|
47
|
+
useIsomorphicLayoutEffect(() => {
|
|
48
|
+
if (tooltipState !== TOOLTIP_STATES.OPENING_PREPARE || !popperElement || !resolvedPlacement) {
|
|
49
|
+
return;
|
|
50
|
+
} // Force layout to register the initial styles with the resolved placement
|
|
51
|
+
// before starting the opening transition.
|
|
18
52
|
|
|
19
|
-
setDummyState(s => !s);
|
|
20
|
-
} else if (stateRef.current === TOOLTIP_STATES.OPENING && isOpen) {
|
|
21
|
-
stateRef.current = TOOLTIP_STATES.OPEN; //force rerender
|
|
22
53
|
|
|
23
|
-
|
|
54
|
+
popperElement.getBoundingClientRect();
|
|
55
|
+
completeOpeningPreparation();
|
|
56
|
+
}, [completeOpeningPreparation, popperElement, resolvedPlacement, tooltipState]); // Track the transitions that currently belong to the OPENING/CLOSING phase:
|
|
57
|
+
// - normally, wait for both opacity and transform before completing the phase;
|
|
58
|
+
// - a style/placement change can cancel or replace a transition without
|
|
59
|
+
// changing the phase; follow the latest one, including a replacement that
|
|
60
|
+
// appears just after the previous transition finishes;
|
|
61
|
+
// - if OPENING changes to CLOSING (or vice versa), cleanup invalidates these
|
|
62
|
+
// waiters and the next phase installs its own, so a stale transition cannot
|
|
63
|
+
// complete it;
|
|
64
|
+
// - if no transitions are created (for example, their duration is 0s),
|
|
65
|
+
// complete the phase immediately.
|
|
66
|
+
|
|
67
|
+
useIsomorphicLayoutEffect(() => {
|
|
68
|
+
if (tooltipState !== TOOLTIP_STATES.OPENING && tooltipState !== TOOLTIP_STATES.CLOSING) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!contentEl) {
|
|
73
|
+
return undefined;
|
|
24
74
|
}
|
|
25
|
-
}, [isOpen]);
|
|
26
75
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
76
|
+
let isCurrentPhase = true;
|
|
77
|
+
|
|
78
|
+
const completeCurrentPhase = () => {
|
|
79
|
+
if (isCurrentPhase) {
|
|
80
|
+
completeTransition(tooltipState);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const waitForCurrentTransition = (property, previousTransition) => {
|
|
85
|
+
if (!isCurrentPhase) {
|
|
86
|
+
return Promise.resolve();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const transition = getTooltipTransition(contentEl, property);
|
|
90
|
+
|
|
91
|
+
if (!transition || transition === previousTransition) {
|
|
92
|
+
return Promise.resolve();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return transition.finished.then(() => {
|
|
96
|
+
if (!isCurrentPhase) {
|
|
97
|
+
return Promise.resolve();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const replacementTransition = getTooltipTransition(contentEl, property);
|
|
101
|
+
|
|
102
|
+
if (replacementTransition && replacementTransition !== transition) {
|
|
103
|
+
return waitForCurrentTransition(property, transition);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return Promise.resolve();
|
|
107
|
+
}, () => waitForCurrentTransition(property, transition));
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
Promise.all(TOOLTIP_TRANSITION_PROPERTIES.map(property => waitForCurrentTransition(property))).then(completeCurrentPhase);
|
|
111
|
+
return () => {
|
|
112
|
+
isCurrentPhase = false;
|
|
113
|
+
};
|
|
114
|
+
}, [completeTransition, contentEl, popperElement, tooltipState]); // React retries this component before rendering its children when the phase changes.
|
|
115
|
+
|
|
116
|
+
if (!canRender && tooltipState !== TOOLTIP_STATES.CLOSE) {
|
|
117
|
+
setTooltipState(TOOLTIP_STATES.CLOSE);
|
|
118
|
+
} else if (isOpen && canRender && tooltipState === TOOLTIP_STATES.CLOSE) {
|
|
119
|
+
setTooltipState(TOOLTIP_STATES.OPENING_PREPARE);
|
|
120
|
+
} else if (isOpen && canRender && tooltipState === TOOLTIP_STATES.CLOSING) {
|
|
121
|
+
setTooltipState(TOOLTIP_STATES.OPENING);
|
|
122
|
+
} else if (!isOpen && tooltipState === TOOLTIP_STATES.OPENING_PREPARE) {
|
|
123
|
+
setTooltipState(TOOLTIP_STATES.CLOSE);
|
|
124
|
+
} else if (!isOpen && (tooltipState === TOOLTIP_STATES.OPEN || tooltipState === TOOLTIP_STATES.OPENING)) {
|
|
125
|
+
setTooltipState(TOOLTIP_STATES.CLOSING);
|
|
31
126
|
}
|
|
32
127
|
|
|
33
|
-
return
|
|
128
|
+
return tooltipState;
|
|
34
129
|
}
|
|
35
130
|
|
|
36
131
|
export { TOOLTIP_STATES, useTooltipState };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rescui/tooltip",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3-RUI-308-Fix-select-issues-405b9fa40.12+405b9fa40",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "JetBrains",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@babel/runtime-corejs3": "^7.26.0",
|
|
20
20
|
"@popperjs/core": "^2.11.8",
|
|
21
|
+
"@rescui/use-resize-observer": "0.3.5-RUI-308-Fix-select-issues-405b9fa40.12+405b9fa40",
|
|
21
22
|
"classnames": "^2.2.6",
|
|
22
23
|
"react-popper": "^2.2.5"
|
|
23
24
|
},
|
|
@@ -28,14 +29,14 @@
|
|
|
28
29
|
"react-dom": ">=16.8.0 <20"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
|
-
"@rescui/colors": "
|
|
32
|
-
"@rescui/icons": "
|
|
33
|
-
"@rescui/scripts": "
|
|
34
|
-
"@rescui/typography": "
|
|
32
|
+
"@rescui/colors": "0.3.4-RUI-308-Fix-select-issues-405b9fa40.12+405b9fa40",
|
|
33
|
+
"@rescui/icons": "1.8.5-RUI-308-Fix-select-issues-405b9fa40.12+405b9fa40",
|
|
34
|
+
"@rescui/scripts": "0.5.2",
|
|
35
|
+
"@rescui/typography": "0.27.5-RUI-308-Fix-select-issues-405b9fa40.12+405b9fa40"
|
|
35
36
|
},
|
|
36
37
|
"scripts": {
|
|
37
38
|
"build": "rescui-scripts build"
|
|
38
39
|
},
|
|
39
40
|
"nx": {},
|
|
40
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "405b9fa40886b0ab6709c9185e8214599d2d792e"
|
|
41
42
|
}
|