@rescui/tooltip 0.10.4-RUI-262-Migrate-to-GH-Actions-Release-dummy-8695a904.3 → 0.10.4-RUI-262-Migrate-to-GH-Actions-Release-dummy-8840066a.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/css-vars-utils.d.ts +3 -0
- package/lib/css-vars-utils.js +20 -0
- package/lib/index.css +143 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +9 -0
- package/lib/tooltip.d.ts +68 -0
- package/lib/tooltip.js +296 -0
- package/lib/tooltip.p.module.css.js +10 -0
- package/lib/use-tooltip-state.d.ts +7 -0
- package/lib/use-tooltip-state.js +36 -0
- package/package.json +5 -5
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const PRIMARY_COLORS = ['--rs-color-primary-light-theme', '--rs-color-primary-dim-light-theme', '--rs-color-primary-fog-light-theme', '--rs-color-primary-t-dim-light-theme', '--rs-color-primary-t-fog-light-theme', '--rs-color-primary-dark-theme', '--rs-color-primary-dim-dark-theme', '--rs-color-primary-fog-dark-theme', '--rs-color-primary-t-dim-dark-theme', '--rs-color-primary-t-fog-dark-theme'];
|
|
2
|
+
|
|
3
|
+
const extractPrimaryColors = styles => {
|
|
4
|
+
const colors = {};
|
|
5
|
+
PRIMARY_COLORS.forEach(varName => {
|
|
6
|
+
colors[varName] = styles.getPropertyValue(varName) || 'initial';
|
|
7
|
+
});
|
|
8
|
+
return colors;
|
|
9
|
+
};
|
|
10
|
+
/** Check out `@rescui/colors/src/public-api.p.css` file */
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const extractThemeFromCss = styles => {
|
|
14
|
+
const themeDark = parseInt(styles.getPropertyValue('--rs-theme-dark'), 10) || 0;
|
|
15
|
+
const themeFlip = parseInt(styles.getPropertyValue('--rs-theme-flip'), 10) || 0;
|
|
16
|
+
const themeDarkCoefficient = themeDark * (1 - themeFlip) + themeFlip * (1 - themeDark);
|
|
17
|
+
return themeDarkCoefficient === 1 ? 'dark' : 'light';
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export { extractPrimaryColors, extractThemeFromCss };
|
package/lib/index.css
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
._tooltip_1nfo2no_5{
|
|
2
|
+
position:relative;
|
|
3
|
+
}
|
|
4
|
+
._closing_1nfo2no_9{
|
|
5
|
+
pointer-events:none;
|
|
6
|
+
}
|
|
7
|
+
._content_1nfo2no_13{
|
|
8
|
+
--rs-theme-dark:1;
|
|
9
|
+
--_rs-tooltip-border-width:1px;
|
|
10
|
+
|
|
11
|
+
--_rs-theme-dark:var(
|
|
12
|
+
--_rs-internal-force-theme-dark-consult-rescui-before-using,
|
|
13
|
+
var(--rs-theme-dark, 0)
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
--_rs-theme-flip:var(--rs-theme-flip, 0);
|
|
17
|
+
|
|
18
|
+
--_rs-theme-dark-coefficient:calc(var(--_rs-theme-dark)*(1 - var(--_rs-theme-flip)) + var(--_rs-theme-flip)*(1 - var(--_rs-theme-dark)));
|
|
19
|
+
|
|
20
|
+
--_rs-theme-light-coefficient:calc(1 - var(--_rs-theme-dark-coefficient));
|
|
21
|
+
letter-spacing:var(
|
|
22
|
+
--rs-text-base-letter-spacing,
|
|
23
|
+
var(--_rs-typography-letter-spacing)
|
|
24
|
+
);
|
|
25
|
+
text-transform:var(--_rs-typography-text-transform);
|
|
26
|
+
font-family:var(--_rs-typography-font-family);
|
|
27
|
+
font-size:var(--_rs-typography-font-size);
|
|
28
|
+
font-weight:var(--_rs-typography-font-weight);
|
|
29
|
+
line-height:var(--_rs-typography-line-height);
|
|
30
|
+
font-variant-numeric:var(--_rs-typography-font-variant-numeric);
|
|
31
|
+
font-feature-settings:'kern', 'liga', 'calt';
|
|
32
|
+
--_rs-typography-letter-spacing:var(--rs-text-3-letter-spacing, 0.0045em);
|
|
33
|
+
--_rs-typography-text-transform:initial;
|
|
34
|
+
--_rs-typography-font-variant-numeric:initial;
|
|
35
|
+
--_rs-typography-font-family:var(
|
|
36
|
+
--rs-font-family-ui,
|
|
37
|
+
var(--rs-font-family-jb-sans, 'JetBrains Sans', Inter, system-ui, -apple-system,
|
|
38
|
+
BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
|
|
39
|
+
'Droid Sans', 'Helvetica Neue', Arial, sans-serif)
|
|
40
|
+
);
|
|
41
|
+
--_rs-typography-font-size:var(--rs-text-3-font-size, 13px);
|
|
42
|
+
--_rs-typography-font-weight:var(
|
|
43
|
+
--rs-font-weight-regular,
|
|
44
|
+
400
|
|
45
|
+
);
|
|
46
|
+
--_rs-typography-line-height:var(
|
|
47
|
+
--rs-text-3-line-height,
|
|
48
|
+
20px
|
|
49
|
+
);
|
|
50
|
+
--_rs-typography-base-color:var(
|
|
51
|
+
--_rs-typography-hardness-color,
|
|
52
|
+
var(
|
|
53
|
+
--rs-color-average,
|
|
54
|
+
rgba(calc(25 + var(--_rs-theme-dark-coefficient, 0)*230), calc(25 + var(--_rs-theme-dark-coefficient, 0)*230), calc(28 + var(--_rs-theme-dark-coefficient, 0)*227), 0.7)
|
|
55
|
+
)
|
|
56
|
+
);
|
|
57
|
+
--_rs-typography-text-auto-offset:8px;
|
|
58
|
+
--_rs-typography-ul-list-li-padding-left:28px;
|
|
59
|
+
--_rs-typography-ol-list-li-padding-left:21px;
|
|
60
|
+
--_rs-typography-list-li-margin-top-from-text:8px;
|
|
61
|
+
--_rs-typography-link-standalone-border-offset-from-text-base:1.15em;
|
|
62
|
+
--_rs-typography-link-external-standalone-border-offset-from-text-base:1.02em;
|
|
63
|
+
--_rs-typography-link-border-bottom-width-from-text:1px;
|
|
64
|
+
|
|
65
|
+
max-width:283px;
|
|
66
|
+
|
|
67
|
+
padding:calc(8px - var(--_rs-tooltip-border-width));
|
|
68
|
+
|
|
69
|
+
border:var(--_rs-tooltip-border-width) solid rgba(255,255,255,0.1);
|
|
70
|
+
border-radius:4px;
|
|
71
|
+
|
|
72
|
+
color:#FFFFFF;
|
|
73
|
+
background-color:#303033;
|
|
74
|
+
|
|
75
|
+
transition:opacity 300ms, transform 300ms;
|
|
76
|
+
transform:translate(0, 0);
|
|
77
|
+
}
|
|
78
|
+
[data-popper-placement='top-end'] ._content_1nfo2no_13,
|
|
79
|
+
[data-popper-placement='bottom-end'] ._content_1nfo2no_13{
|
|
80
|
+
margin-right:0;
|
|
81
|
+
}
|
|
82
|
+
[data-popper-placement='top-start'] ._content_1nfo2no_13,
|
|
83
|
+
[data-popper-placement='bottom-start'] ._content_1nfo2no_13{
|
|
84
|
+
margin-left:0;
|
|
85
|
+
}
|
|
86
|
+
[data-popper-placement='left-end'] ._content_1nfo2no_13,
|
|
87
|
+
[data-popper-placement='right-end'] ._content_1nfo2no_13{
|
|
88
|
+
margin-bottom:0;
|
|
89
|
+
}
|
|
90
|
+
[data-popper-placement='left-start'] ._content_1nfo2no_13,
|
|
91
|
+
[data-popper-placement='right-start'] ._content_1nfo2no_13{
|
|
92
|
+
margin-top:0;
|
|
93
|
+
}
|
|
94
|
+
._initial_1nfo2no_54 ._content_1nfo2no_13{
|
|
95
|
+
transition:none;
|
|
96
|
+
}
|
|
97
|
+
._closing_1nfo2no_9 ._content_1nfo2no_13{
|
|
98
|
+
transition-duration:200ms, 200ms;
|
|
99
|
+
}
|
|
100
|
+
._initial_1nfo2no_54 ._content_1nfo2no_13,
|
|
101
|
+
._closing_1nfo2no_9 ._content_1nfo2no_13{
|
|
102
|
+
opacity:0;
|
|
103
|
+
}
|
|
104
|
+
._outerThemeLight_1nfo2no_68 ._content_1nfo2no_13{
|
|
105
|
+
--rs-color-primary-dark-theme:var(--rs-color-primary-light-theme);
|
|
106
|
+
--rs-color-primary-dim-dark-theme:var(--rs-color-primary-dim-light-theme);
|
|
107
|
+
--rs-color-primary-fog-dark-theme:var(--rs-color-primary-fog-light-theme);
|
|
108
|
+
--rs-color-primary-t-dim-dark-theme:var(
|
|
109
|
+
--rs-color-primary-t-dim-light-theme
|
|
110
|
+
);
|
|
111
|
+
--rs-color-primary-t-fog-dark-theme:var(
|
|
112
|
+
--rs-color-primary-t-fog-light-theme
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
._outerThemeDark_1nfo2no_81 ._content_1nfo2no_13{
|
|
116
|
+
--rs-color-primary-light-theme:var(--rs-color-primary-dark-theme);
|
|
117
|
+
--rs-color-primary-dim-light-theme:var(--rs-color-primary-dim-dark-theme);
|
|
118
|
+
--rs-color-primary-fog-light-theme:var(--rs-color-primary-fog-dark-theme);
|
|
119
|
+
--rs-color-primary-t-dim-light-theme:var(
|
|
120
|
+
--rs-color-primary-t-dim-dark-theme
|
|
121
|
+
);
|
|
122
|
+
--rs-color-primary-t-fog-light-theme:var(
|
|
123
|
+
--rs-color-primary-t-fog-dark-theme
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
._initial_1nfo2no_54[data-popper-placement^='top'] ._content_1nfo2no_13, ._closing_1nfo2no_9[data-popper-placement^='top'] ._content_1nfo2no_13{
|
|
127
|
+
transform:translate(0, 10px);
|
|
128
|
+
}
|
|
129
|
+
._initial_1nfo2no_54[data-popper-placement^='right'] ._content_1nfo2no_13, ._closing_1nfo2no_9[data-popper-placement^='right'] ._content_1nfo2no_13{
|
|
130
|
+
transform:translate(-10px, 0);
|
|
131
|
+
}
|
|
132
|
+
._initial_1nfo2no_54[data-popper-placement^='bottom'] ._content_1nfo2no_13, ._closing_1nfo2no_9[data-popper-placement^='bottom'] ._content_1nfo2no_13{
|
|
133
|
+
transform:translate(0, -10px);
|
|
134
|
+
}
|
|
135
|
+
._initial_1nfo2no_54[data-popper-placement^='left'] ._content_1nfo2no_13, ._closing_1nfo2no_9[data-popper-placement^='left'] ._content_1nfo2no_13{
|
|
136
|
+
transform:translate(10px, 0);
|
|
137
|
+
}
|
|
138
|
+
._trigger_1nfo2no_113:focus-visible,
|
|
139
|
+
._trigger_1nfo2no_113:focus[data-focus-method='key']{
|
|
140
|
+
outline:none;
|
|
141
|
+
|
|
142
|
+
box-shadow:var(--rs-color-primary-t-dim-light-theme) 0 0 0 4px;
|
|
143
|
+
}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated use named import instead
|
|
4
|
+
*/
|
|
5
|
+
declare const DefaultTooltip: import("react").FC<import("./tooltip").TooltipProps>;
|
|
6
|
+
export default DefaultTooltip;
|
|
7
|
+
export { Tooltip } from './tooltip';
|
|
8
|
+
export type { TooltipProps, TooltipPlacement } from './tooltip';
|
package/lib/index.js
ADDED
package/lib/tooltip.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StrictModifiers } from '@popperjs/core/lib/types';
|
|
3
|
+
import type { Placement } from '@popperjs/core/lib/enums';
|
|
4
|
+
interface TriggerTargetRequiredProps {
|
|
5
|
+
ref: React.Ref<HTMLElement>;
|
|
6
|
+
}
|
|
7
|
+
interface TriggerTargetAdditionalProps {
|
|
8
|
+
onBlur: (...args: unknown[]) => void;
|
|
9
|
+
tabIndex: number;
|
|
10
|
+
onMouseEnter: (...args: unknown[]) => void;
|
|
11
|
+
onMouseLeave: (...args: unknown[]) => void;
|
|
12
|
+
onFocus: (...args: unknown[]) => void;
|
|
13
|
+
}
|
|
14
|
+
declare type TriggerTargetProps = TriggerTargetRequiredProps | (TriggerTargetRequiredProps & TriggerTargetAdditionalProps);
|
|
15
|
+
declare type ChildrenFunc = (arg: {
|
|
16
|
+
targetProps: TriggerTargetProps;
|
|
17
|
+
}) => React.ReactNode;
|
|
18
|
+
export declare type TooltipChildren = ChildrenFunc | React.ReactNode;
|
|
19
|
+
export declare type TooltipPlacement = 'auto-start' | 'auto' | 'auto-end' | 'top-start' | 'top' | 'top-end' | 'right-start' | 'right' | 'right-end' | 'bottom-end' | 'bottom' | 'bottom-start' | 'left-end' | 'left' | 'left-start';
|
|
20
|
+
export interface TooltipProps {
|
|
21
|
+
/**
|
|
22
|
+
* Target node or `({targetProps}) => node` function
|
|
23
|
+
* @type (arg: { targetProps: TriggerTargetProps; }) => ReactNode | ReactNode
|
|
24
|
+
*/
|
|
25
|
+
children: TooltipChildren;
|
|
26
|
+
/**
|
|
27
|
+
* Wrapper component type if children is not a function
|
|
28
|
+
*/
|
|
29
|
+
targetComponent?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Tooltip content
|
|
32
|
+
*/
|
|
33
|
+
content?: React.ReactNode;
|
|
34
|
+
className?: string;
|
|
35
|
+
/**
|
|
36
|
+
* "External" state control
|
|
37
|
+
*/
|
|
38
|
+
isVisible?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Pooper.js [modifiers](https://popper.js.org/docs/v2/modifiers/) config
|
|
41
|
+
*/
|
|
42
|
+
modifiers?: StrictModifiers[];
|
|
43
|
+
/**
|
|
44
|
+
* Please use only `auto`, `top-end`, `right`, `left`, `right-start` or `left-start` to be compliant with styleguide
|
|
45
|
+
*/
|
|
46
|
+
placement?: TooltipPlacement;
|
|
47
|
+
/**
|
|
48
|
+
* When no space is available on the preferred placement, the tooltip will test
|
|
49
|
+
* the ones provided in the list, and use the first useful one.
|
|
50
|
+
* See [docs](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements).
|
|
51
|
+
*/
|
|
52
|
+
fallbackPlacements?: Placement[];
|
|
53
|
+
/**
|
|
54
|
+
* Disable timeout before hide tooltip after mouse left target,
|
|
55
|
+
* use with cation, it can make impossible to click on links inside tooltip
|
|
56
|
+
*/
|
|
57
|
+
disableHideDelay?: boolean;
|
|
58
|
+
/** increase offset from the target */
|
|
59
|
+
sparse?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* If set to true, the tooltip will be rendered adjacent to its triggering element.
|
|
62
|
+
* If false or undefined, the tooltip will render at the end of the `document.body` element.
|
|
63
|
+
* Should be used when the tooltip content contains interactive elements (e.g. links).
|
|
64
|
+
*/
|
|
65
|
+
renderBesideTrigger?: boolean;
|
|
66
|
+
}
|
|
67
|
+
export declare const Tooltip: React.FC<TooltipProps>;
|
|
68
|
+
export default Tooltip;
|
package/lib/tooltip.js
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
|
|
3
|
+
import React, { cloneElement, createElement, useState, useRef, useEffect, useCallback, useContext, isValidElement } from 'react';
|
|
4
|
+
import { Element, ForwardRef, typeOf } from 'react-is';
|
|
5
|
+
import cn from 'classnames';
|
|
6
|
+
import PropTypes from 'prop-types';
|
|
7
|
+
import ReactDOM from 'react-dom';
|
|
8
|
+
import { usePopper } from 'react-popper';
|
|
9
|
+
import { useLayeringContext, ThemeContext, ThemeProvider } from '@rescui/ui-contexts';
|
|
10
|
+
import styles from './tooltip.p.module.css.js';
|
|
11
|
+
import { useTooltipState, TOOLTIP_STATES } from './use-tooltip-state.js';
|
|
12
|
+
import { extractThemeFromCss, extractPrimaryColors } from './css-vars-utils.js';
|
|
13
|
+
const HIDE_TIMEOUT = 500;
|
|
14
|
+
|
|
15
|
+
const Portal = _ref => {
|
|
16
|
+
let {
|
|
17
|
+
children,
|
|
18
|
+
target = typeof window !== 'undefined' ? document.body : undefined
|
|
19
|
+
} = _ref;
|
|
20
|
+
return target ? /*#__PURE__*/ReactDOM.createPortal(children, target) : null;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const isNode = maybeNode => {
|
|
24
|
+
switch (typeof maybeNode) {
|
|
25
|
+
case 'string':
|
|
26
|
+
case 'number':
|
|
27
|
+
return true;
|
|
28
|
+
|
|
29
|
+
case 'object':
|
|
30
|
+
if ( /*#__PURE__*/isValidElement(maybeNode)) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (Array.isArray(maybeNode)) {
|
|
35
|
+
return maybeNode.every(isNode);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return false;
|
|
39
|
+
|
|
40
|
+
default:
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const OUTER_THEME_STYLES = {
|
|
46
|
+
light: styles.outerThemeLight,
|
|
47
|
+
dark: styles.outerThemeDark
|
|
48
|
+
};
|
|
49
|
+
const TriggerRenderer = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
50
|
+
var _children$props, _context;
|
|
51
|
+
|
|
52
|
+
let {
|
|
53
|
+
setTriggerRef,
|
|
54
|
+
targetComponent,
|
|
55
|
+
isControlled,
|
|
56
|
+
handleMouseEnterTarget,
|
|
57
|
+
handleMouseLeaveTarget,
|
|
58
|
+
children
|
|
59
|
+
} = _ref2;
|
|
60
|
+
const eventListeners = !isControlled ? {
|
|
61
|
+
onMouseEnter: handleMouseEnterTarget,
|
|
62
|
+
onMouseLeave: handleMouseLeaveTarget,
|
|
63
|
+
onFocus: handleMouseEnterTarget,
|
|
64
|
+
onBlur: handleMouseLeaveTarget,
|
|
65
|
+
tabIndex: 0
|
|
66
|
+
} : {};
|
|
67
|
+
const childrenRef = (children === null || children === void 0 ? void 0 : children.ref) ?? (children === null || children === void 0 || (_children$props = children.props) === null || _children$props === void 0 ? void 0 : _children$props.ref);
|
|
68
|
+
const tooltipTargetProps = Object.assign({}, {
|
|
69
|
+
ref: el => {
|
|
70
|
+
setTriggerRef(el);
|
|
71
|
+
|
|
72
|
+
if (childrenRef) {
|
|
73
|
+
if (typeof childrenRef === 'function') {
|
|
74
|
+
childrenRef(el);
|
|
75
|
+
} else {
|
|
76
|
+
childrenRef.current = el;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (ref) {
|
|
81
|
+
if (typeof ref === 'function') {
|
|
82
|
+
ref(el);
|
|
83
|
+
} else {
|
|
84
|
+
ref.current = el;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}, eventListeners);
|
|
89
|
+
|
|
90
|
+
if (typeof children === 'function') {
|
|
91
|
+
return children({
|
|
92
|
+
targetProps: tooltipTargetProps
|
|
93
|
+
});
|
|
94
|
+
} else if (_includesInstanceProperty(_context = [Element, ForwardRef]).call(_context, typeOf(children))) {
|
|
95
|
+
return /*#__PURE__*/cloneElement(children, {
|
|
96
|
+
className: cn(styles.trigger, children.props.className),
|
|
97
|
+
...tooltipTargetProps
|
|
98
|
+
});
|
|
99
|
+
} // create trigger-wrapper to bind tooltip
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
return /*#__PURE__*/createElement(targetComponent, {
|
|
103
|
+
className: styles.trigger,
|
|
104
|
+
...tooltipTargetProps
|
|
105
|
+
}, children);
|
|
106
|
+
});
|
|
107
|
+
TriggerRenderer.displayName = 'TriggerRenderer'; // eslint-disable-next-line complexity
|
|
108
|
+
|
|
109
|
+
const Tooltip = _ref3 => {
|
|
110
|
+
let {
|
|
111
|
+
children,
|
|
112
|
+
targetComponent = 'span',
|
|
113
|
+
content,
|
|
114
|
+
className,
|
|
115
|
+
isVisible: isVisibleFromProps,
|
|
116
|
+
modifiers,
|
|
117
|
+
placement = 'auto',
|
|
118
|
+
sparse = true,
|
|
119
|
+
fallbackPlacements = ['top', 'bottom'],
|
|
120
|
+
disableHideDelay,
|
|
121
|
+
renderBesideTrigger = false
|
|
122
|
+
} = _ref3;
|
|
123
|
+
const {
|
|
124
|
+
tooltipZIndex
|
|
125
|
+
} = useLayeringContext();
|
|
126
|
+
const [popperRef, setPopperRef] = useState(null);
|
|
127
|
+
const [triggerRef, setTriggerRef] = useState(null);
|
|
128
|
+
const [isVisibleState, setIsVisibleState] = useState(false);
|
|
129
|
+
const [isTooltipHovered, setIsTooltipHovered] = useState(false);
|
|
130
|
+
const schedulePopperUpdateRef = useRef(null);
|
|
131
|
+
const contentRef = useRef(null);
|
|
132
|
+
const hideTimeoutRef = useRef(null);
|
|
133
|
+
const isControlled = typeof isVisibleFromProps !== 'undefined';
|
|
134
|
+
let isVisible = isControlled ? isVisibleFromProps : isVisibleState; // We set isVisible this way to avoid hydration issue due to
|
|
135
|
+
// the Portal to document.body which does not exist on the server.
|
|
136
|
+
// So even if isVisible prop is used, the tooltip will not render on the server, and
|
|
137
|
+
// it's the same on the first client render, so there is no hydration issue.
|
|
138
|
+
|
|
139
|
+
const [isFirstRender, setIsFirstRender] = useState(true);
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
setIsFirstRender(false);
|
|
142
|
+
}, []);
|
|
143
|
+
isVisible = isFirstRender && !renderBesideTrigger ? false : isVisible;
|
|
144
|
+
const isOpen = isVisible || isTooltipHovered;
|
|
145
|
+
const PortalResolved = renderBesideTrigger ? React.Fragment : Portal;
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
if (schedulePopperUpdateRef.current) {
|
|
148
|
+
schedulePopperUpdateRef.current();
|
|
149
|
+
}
|
|
150
|
+
}, [content]);
|
|
151
|
+
|
|
152
|
+
const handleMouseEnterTarget = () => {
|
|
153
|
+
if (hideTimeoutRef.current) {
|
|
154
|
+
clearTimeout(hideTimeoutRef.current);
|
|
155
|
+
hideTimeoutRef.current = null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
setIsVisibleState(true);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const handleMouseLeaveTarget = () => {
|
|
162
|
+
if (disableHideDelay) {
|
|
163
|
+
setIsVisibleState(false);
|
|
164
|
+
} else {
|
|
165
|
+
hideTimeoutRef.current = setTimeout(() => {
|
|
166
|
+
setIsVisibleState(false);
|
|
167
|
+
}, HIDE_TIMEOUT);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const [handleAnimationEnd, tooltipState] = useTooltipState(isOpen);
|
|
172
|
+
const isClosing = tooltipState === TOOLTIP_STATES.CLOSING;
|
|
173
|
+
const isExists = tooltipState !== TOOLTIP_STATES.CLOSE; // a state to toggle the starting transition
|
|
174
|
+
|
|
175
|
+
const [isInitial, setIsInitial] = useState(true); // reset the initial flag when the closing transition ends and the state switches to CLOSED
|
|
176
|
+
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
if (!isExists) {
|
|
179
|
+
setIsInitial(true);
|
|
180
|
+
}
|
|
181
|
+
}, [isExists]);
|
|
182
|
+
const disableInitialFlag = useCallback(_ref4 => {
|
|
183
|
+
let {
|
|
184
|
+
state
|
|
185
|
+
} = _ref4;
|
|
186
|
+
const el = state.elements.popper; // force layout phase
|
|
187
|
+
// to make sure that the dom has registered the initial
|
|
188
|
+
// styles with resolved placement (for `auto` placement)
|
|
189
|
+
|
|
190
|
+
el.getBoundingClientRect();
|
|
191
|
+
setIsInitial(false);
|
|
192
|
+
}, []);
|
|
193
|
+
const tooltipShouldBeRendered = isExists && isNode(content);
|
|
194
|
+
let primaryColors = {};
|
|
195
|
+
let themeFromCss = 'light';
|
|
196
|
+
|
|
197
|
+
if (triggerRef && tooltipShouldBeRendered) {
|
|
198
|
+
// In theory this part of the code might cause issues with SSR.
|
|
199
|
+
// But in this specific context, because of the nature of the state-ref "triggerRef",
|
|
200
|
+
// we are sure that the tooltip wouldn't be rendered on the first client render.
|
|
201
|
+
// Therefore, the first render on the client will be the same as on the server.
|
|
202
|
+
const triggerStyles = getComputedStyle(triggerRef);
|
|
203
|
+
themeFromCss = extractThemeFromCss(triggerStyles);
|
|
204
|
+
primaryColors = extractPrimaryColors(triggerStyles);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const {
|
|
208
|
+
theme: themeFromContext,
|
|
209
|
+
noProvider
|
|
210
|
+
} = useContext(ThemeContext);
|
|
211
|
+
const theme = noProvider ? themeFromCss : themeFromContext;
|
|
212
|
+
const calcOffset = useCallback(_ref5 => {
|
|
213
|
+
let {
|
|
214
|
+
placement: offsetPlacement
|
|
215
|
+
} = _ref5;
|
|
216
|
+
|
|
217
|
+
if (_includesInstanceProperty(offsetPlacement).call(offsetPlacement, 'left') || _includesInstanceProperty(offsetPlacement).call(offsetPlacement, 'right')) {
|
|
218
|
+
return [0, sparse ? 16 : 8];
|
|
219
|
+
} else {
|
|
220
|
+
return [0, sparse ? 12 : 8];
|
|
221
|
+
}
|
|
222
|
+
}, [sparse]);
|
|
223
|
+
const {
|
|
224
|
+
styles: popperStyles,
|
|
225
|
+
attributes,
|
|
226
|
+
update
|
|
227
|
+
} = usePopper(triggerRef, popperRef, {
|
|
228
|
+
placement,
|
|
229
|
+
modifiers: [// the modifier to trigger starting animation
|
|
230
|
+
{
|
|
231
|
+
name: 'disableInitialFlag',
|
|
232
|
+
enabled: true,
|
|
233
|
+
phase: 'afterWrite',
|
|
234
|
+
fn: disableInitialFlag,
|
|
235
|
+
requires: []
|
|
236
|
+
}, {
|
|
237
|
+
name: 'flip',
|
|
238
|
+
options: {
|
|
239
|
+
fallbackPlacements
|
|
240
|
+
}
|
|
241
|
+
}, {
|
|
242
|
+
name: 'offset',
|
|
243
|
+
options: {
|
|
244
|
+
offset: calcOffset
|
|
245
|
+
}
|
|
246
|
+
}, ...(modifiers || [])]
|
|
247
|
+
});
|
|
248
|
+
schedulePopperUpdateRef.current = update;
|
|
249
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TriggerRenderer, {
|
|
250
|
+
setTriggerRef: setTriggerRef,
|
|
251
|
+
targetComponent: targetComponent,
|
|
252
|
+
isControlled: isControlled,
|
|
253
|
+
handleMouseEnterTarget: handleMouseEnterTarget,
|
|
254
|
+
handleMouseLeaveTarget: handleMouseLeaveTarget
|
|
255
|
+
}, children), tooltipShouldBeRendered && /*#__PURE__*/React.createElement(PortalResolved, null, /*#__PURE__*/React.createElement("span", {
|
|
256
|
+
className: cn(styles.tooltip, isInitial && styles.initial, isClosing && styles.closing, OUTER_THEME_STYLES[theme], className),
|
|
257
|
+
ref: setPopperRef,
|
|
258
|
+
style: { ...popperStyles.popper,
|
|
259
|
+
...primaryColors,
|
|
260
|
+
zIndex: tooltipZIndex
|
|
261
|
+
},
|
|
262
|
+
onMouseEnter: () => setIsTooltipHovered(true),
|
|
263
|
+
onMouseLeave: () => {
|
|
264
|
+
setIsVisibleState(false);
|
|
265
|
+
setIsTooltipHovered(false);
|
|
266
|
+
},
|
|
267
|
+
"data-placement": placement,
|
|
268
|
+
"data-test": "tooltip",
|
|
269
|
+
...attributes.popper
|
|
270
|
+
}, /*#__PURE__*/React.createElement(ThemeProvider, {
|
|
271
|
+
theme: "dark",
|
|
272
|
+
ignoreThemeValueForCSSApi: noProvider
|
|
273
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
274
|
+
className: cn(styles.content),
|
|
275
|
+
onBlur: handleMouseLeaveTarget,
|
|
276
|
+
onFocus: handleMouseEnterTarget,
|
|
277
|
+
onTransitionEnd: handleAnimationEnd,
|
|
278
|
+
onAnimationEnd: handleAnimationEnd,
|
|
279
|
+
ref: contentRef
|
|
280
|
+
}, content)))));
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
Tooltip.propTypes = {
|
|
284
|
+
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
|
|
285
|
+
targetComponent: PropTypes.string,
|
|
286
|
+
content: PropTypes.node,
|
|
287
|
+
className: PropTypes.string,
|
|
288
|
+
isVisible: PropTypes.bool,
|
|
289
|
+
modifiers: PropTypes.array,
|
|
290
|
+
placement: PropTypes.oneOf(['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']),
|
|
291
|
+
fallbackPlacements: PropTypes.arrayOf(PropTypes.oneOf(['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'])),
|
|
292
|
+
sparse: PropTypes.bool,
|
|
293
|
+
disableHideDelay: PropTypes.bool,
|
|
294
|
+
renderBesideTrigger: PropTypes.bool
|
|
295
|
+
};
|
|
296
|
+
export { Tooltip, Tooltip as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var styles = {
|
|
2
|
+
"tooltip": "_tooltip_1nfo2no_5",
|
|
3
|
+
"closing": "_closing_1nfo2no_9",
|
|
4
|
+
"content": "_content_1nfo2no_13",
|
|
5
|
+
"initial": "_initial_1nfo2no_54",
|
|
6
|
+
"outerThemeLight": "_outerThemeLight_1nfo2no_68",
|
|
7
|
+
"outerThemeDark": "_outerThemeDark_1nfo2no_81",
|
|
8
|
+
"trigger": "_trigger_1nfo2no_113"
|
|
9
|
+
};
|
|
10
|
+
export { styles as default };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState, useRef, useCallback } from 'react';
|
|
3
|
+
var TOOLTIP_STATES;
|
|
4
|
+
|
|
5
|
+
(function (TOOLTIP_STATES) {
|
|
6
|
+
TOOLTIP_STATES["OPENING"] = "OPENING";
|
|
7
|
+
TOOLTIP_STATES["OPEN"] = "OPEN";
|
|
8
|
+
TOOLTIP_STATES["CLOSING"] = "CLOSING";
|
|
9
|
+
TOOLTIP_STATES["CLOSE"] = "CLOSE";
|
|
10
|
+
})(TOOLTIP_STATES || (TOOLTIP_STATES = {}));
|
|
11
|
+
|
|
12
|
+
function useTooltipState(isOpen) {
|
|
13
|
+
const [, setDummyState] = useState(false);
|
|
14
|
+
const stateRef = useRef(TOOLTIP_STATES.CLOSE);
|
|
15
|
+
const onAnimationEnd = useCallback(() => {
|
|
16
|
+
if ((stateRef.current === TOOLTIP_STATES.CLOSING || stateRef.current === TOOLTIP_STATES.OPENING) && !isOpen) {
|
|
17
|
+
stateRef.current = TOOLTIP_STATES.CLOSE; //force rerender
|
|
18
|
+
|
|
19
|
+
setDummyState(s => !s);
|
|
20
|
+
} else if (stateRef.current === TOOLTIP_STATES.OPENING && isOpen) {
|
|
21
|
+
stateRef.current = TOOLTIP_STATES.OPEN; //force rerender
|
|
22
|
+
|
|
23
|
+
setDummyState(s => !s);
|
|
24
|
+
}
|
|
25
|
+
}, [isOpen]);
|
|
26
|
+
|
|
27
|
+
if (isOpen && stateRef.current !== TOOLTIP_STATES.OPEN) {
|
|
28
|
+
stateRef.current = TOOLTIP_STATES.OPENING;
|
|
29
|
+
} else if (stateRef.current === TOOLTIP_STATES.OPEN && !isOpen) {
|
|
30
|
+
stateRef.current = TOOLTIP_STATES.CLOSING;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return [onAnimationEnd, stateRef.current];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { TOOLTIP_STATES, useTooltipState };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rescui/tooltip",
|
|
3
|
-
"version": "0.10.4-RUI-262-Migrate-to-GH-Actions-Release-dummy-
|
|
3
|
+
"version": "0.10.4-RUI-262-Migrate-to-GH-Actions-Release-dummy-8840066a.12+8840066a",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "JetBrains",
|
|
@@ -28,15 +28,15 @@
|
|
|
28
28
|
"react-dom": ">=16.8.0 <20"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@rescui/colors": "0.2.11-RUI-262-Migrate-to-GH-Actions-Release-dummy-
|
|
32
|
-
"@rescui/icons": "1.6.1-RUI-262-Migrate-to-GH-Actions-Release-dummy-
|
|
31
|
+
"@rescui/colors": "0.2.11-RUI-262-Migrate-to-GH-Actions-Release-dummy-8840066a.28+8840066a",
|
|
32
|
+
"@rescui/icons": "1.6.1-RUI-262-Migrate-to-GH-Actions-Release-dummy-8840066a.12+8840066a",
|
|
33
33
|
"@rescui/scripts": "0.5.1",
|
|
34
|
-
"@rescui/typography": "0.24.1-RUI-262-Migrate-to-GH-Actions-Release-dummy-
|
|
34
|
+
"@rescui/typography": "0.24.1-RUI-262-Migrate-to-GH-Actions-Release-dummy-8840066a.28+8840066a",
|
|
35
35
|
"@types/react-is": "^17.0.3"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "rescui-scripts build"
|
|
39
39
|
},
|
|
40
40
|
"nx": {},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "8840066a6441a9b7a6d42ca35d3f3fbccc983457"
|
|
42
42
|
}
|