@homecode/ui 5.3.13 → 5.4.1
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/dist/esm/index.js +1 -0
- package/dist/esm/src/components/Autocomplete/Autocomplete.js +2 -1
- package/dist/esm/src/components/InputFile/InputFile.js +2 -1
- package/dist/esm/src/components/TextWithDeferTooltip/TextWithDeferTooltip.js +36 -0
- package/dist/esm/src/components/TextWithDeferTooltip/TextWithDeferTooltip.styl.js +7 -0
- package/dist/esm/src/components/Tooltip/Tooltip.js +9 -80
- package/dist/esm/src/components/Tooltip/Tooltip.styl.js +2 -2
- package/dist/esm/src/components/Tooltip/TooltipCore.js +19 -0
- package/dist/esm/src/components/Tooltip/TooltipOverTrigger.js +96 -0
- package/dist/esm/src/components/Tooltip/TooltipSimple.js +70 -0
- package/dist/esm/src/components/Tooltip/tooltipTextStyles.js +49 -0
- package/dist/esm/types/src/components/TextWithDeferTooltip/TextWithDeferTooltip.d.ts +3 -0
- package/dist/esm/types/src/components/TextWithDeferTooltip/TextWithDeferTooltip.types.d.ts +9 -0
- package/dist/esm/types/src/components/TextWithDeferTooltip/index.d.ts +2 -0
- package/dist/esm/types/src/components/Tooltip/Tooltip.d.ts +2 -1
- package/dist/esm/types/src/components/Tooltip/TooltipCore.d.ts +21 -0
- package/dist/esm/types/src/components/Tooltip/TooltipOverTrigger.d.ts +4 -0
- package/dist/esm/types/src/components/Tooltip/TooltipSimple.d.ts +3 -0
- package/dist/esm/types/src/components/Tooltip/tooltipTextStyles.d.ts +4 -0
- package/dist/esm/types/src/components/index.d.ts +1 -0
- package/graphify-out/.graphify_labels.json +0 -16
- package/graphify-out/2026-07-06/.graphify_labels.json +205 -0
- package/graphify-out/2026-07-06/GRAPH_REPORT.md +982 -0
- package/graphify-out/2026-07-06/cost.json +12 -0
- package/graphify-out/2026-07-06/graph.json +69192 -0
- package/graphify-out/2026-07-06/manifest.json +2262 -0
- package/graphify-out/GRAPH_REPORT.md +144 -186
- package/graphify-out/cache/ast/bed2f246f6c9c3ea5684794da1d417f0b93566753c0a3d0e754c68004dc2c09d.json +1 -0
- package/graphify-out/cache/ast/c041441cf64e84e32561e522d6d368ea363be52429220a3310c91a358c1a0871.json +1 -0
- package/graphify-out/cache/stat-index.json +1 -1
- package/graphify-out/graph.html +4 -4
- package/graphify-out/graph.json +3564 -2548
- package/graphify-out/manifest.json +42 -27
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -49,6 +49,7 @@ export { Spinner } from './src/components/Spinner/Spinner.js';
|
|
|
49
49
|
export { Table } from './src/components/Table/Table.js';
|
|
50
50
|
export { Tabs } from './src/components/Tabs/Tabs.js';
|
|
51
51
|
export { TextShimmer } from './src/components/TextShimmer/TextShimmer.js';
|
|
52
|
+
export { TextWithDeferTooltip } from './src/components/TextWithDeferTooltip/TextWithDeferTooltip.js';
|
|
52
53
|
export { Tooltip } from './src/components/Tooltip/Tooltip.js';
|
|
53
54
|
export { H1, H2, H3, H4, H5, H6 } from './src/components/Text/Text.js';
|
|
54
55
|
export { Theme } from './src/components/Theme/Theme.js';
|
|
@@ -25,7 +25,7 @@ import 'justorm/react';
|
|
|
25
25
|
import 'nanoid';
|
|
26
26
|
import '../Checkbox/Checkbox.styl.js';
|
|
27
27
|
import '../Chip/Chip.styl.js';
|
|
28
|
-
import '../Tooltip/Tooltip.
|
|
28
|
+
import '../Tooltip/Tooltip.js';
|
|
29
29
|
import '../Card/Card.js';
|
|
30
30
|
import '../Container/Container.js';
|
|
31
31
|
import '../DatePicker/DatePicker.styl.js';
|
|
@@ -68,6 +68,7 @@ import '../Slider/Slider.styl.js';
|
|
|
68
68
|
import '../Table/Table.styl.js';
|
|
69
69
|
import '../Tabs/Tabs.styl.js';
|
|
70
70
|
import '../TextShimmer/TextShimmer.js';
|
|
71
|
+
import '../TextWithDeferTooltip/TextWithDeferTooltip.styl.js';
|
|
71
72
|
import '../Text/Text.js';
|
|
72
73
|
import '../Theme/Theme.defaults.js';
|
|
73
74
|
import '../Theme/ThemeProvider.js';
|
|
@@ -30,7 +30,7 @@ import '../RequiredStar/RequiredStar.styl.js';
|
|
|
30
30
|
import '../Select/Select.styl.js';
|
|
31
31
|
import '../Checkbox/Checkbox.styl.js';
|
|
32
32
|
import '../Chip/Chip.styl.js';
|
|
33
|
-
import '../Tooltip/Tooltip.
|
|
33
|
+
import '../Tooltip/Tooltip.js';
|
|
34
34
|
import '../Card/Card.js';
|
|
35
35
|
import '../Container/Container.js';
|
|
36
36
|
import '../DatePicker/DatePicker.styl.js';
|
|
@@ -68,6 +68,7 @@ import '../Slider/Slider.styl.js';
|
|
|
68
68
|
import '../Table/Table.styl.js';
|
|
69
69
|
import '../Tabs/Tabs.styl.js';
|
|
70
70
|
import '../TextShimmer/TextShimmer.js';
|
|
71
|
+
import '../TextWithDeferTooltip/TextWithDeferTooltip.styl.js';
|
|
71
72
|
import '../Text/Text.js';
|
|
72
73
|
import '../Theme/Theme.defaults.js';
|
|
73
74
|
import '../Theme/ThemeProvider.js';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useRef } from 'react';
|
|
3
|
+
import { Tooltip } from '../Tooltip/Tooltip.js';
|
|
4
|
+
import S from './TextWithDeferTooltip.styl.js';
|
|
5
|
+
|
|
6
|
+
function TextWithDeferTooltip({ className, children, width, maxWidth, side = 'bottom', overTrigger = false, ...props }) {
|
|
7
|
+
const [withTooltip, setWithTooltip] = useState(false);
|
|
8
|
+
const [tooltipWidth, setTooltipWidth] = useState();
|
|
9
|
+
const ref = useRef(null);
|
|
10
|
+
const handleMouseLeave = () => setWithTooltip(false);
|
|
11
|
+
const handleMouseEnter = () => {
|
|
12
|
+
if (!ref.current)
|
|
13
|
+
return;
|
|
14
|
+
const isOverflowingHorizontally = ref.current.scrollWidth - ref.current.clientWidth > 3;
|
|
15
|
+
const isOverflowingVertically = ref.current.scrollHeight - ref.current.clientHeight > 3;
|
|
16
|
+
if (isOverflowingHorizontally || isOverflowingVertically) {
|
|
17
|
+
if (width != null) {
|
|
18
|
+
setTooltipWidth(width);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
setTooltipWidth(ref.current.getBoundingClientRect().width);
|
|
22
|
+
}
|
|
23
|
+
setWithTooltip(true);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const tooltipContent = maxWidth != null || tooltipWidth != null ? (jsx("div", { style: {
|
|
27
|
+
...(maxWidth != null && { maxWidth: `${maxWidth}px` }),
|
|
28
|
+
...(tooltipWidth != null &&
|
|
29
|
+
!overTrigger && { width: `${tooltipWidth}px` }),
|
|
30
|
+
}, children: children })) : (children);
|
|
31
|
+
return (jsx(Tooltip, { className: S.tooltipTrigger, content: tooltipContent, contentClassName: (maxWidth != null || tooltipWidth != null) && !overTrigger
|
|
32
|
+
? S.tooltipShell
|
|
33
|
+
: undefined, disabled: !withTooltip, direction: overTrigger ? 'bottom' : side, overTrigger: overTrigger, children: jsx("div", { ref: ref, className: className, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, ...props, children: children }) }));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { TextWithDeferTooltip };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import styleInject from '../../../node_modules/style-inject/dist/style-inject.es.js';
|
|
2
|
+
|
|
3
|
+
var css_248z = ".TextWithDeferTooltip_tooltipTrigger__bmoIx{box-sizing:border-box;display:block!important;max-width:100%;width:100%}.TextWithDeferTooltip_tooltipShell__PXlL4{max-width:none!important}";
|
|
4
|
+
var S = {"tooltipTrigger":"TextWithDeferTooltip_tooltipTrigger__bmoIx","tooltipShell":"TextWithDeferTooltip_tooltipShell__PXlL4"};
|
|
5
|
+
styleInject(css_248z);
|
|
6
|
+
|
|
7
|
+
export { S as default };
|
|
@@ -1,86 +1,15 @@
|
|
|
1
|
-
import { jsx, Fragment
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import cn from 'classnames';
|
|
1
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { lazy, Suspense } from 'react';
|
|
3
|
+
import { TooltipSimple } from './TooltipSimple.js';
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* - Positioning logic that calculates optimal tooltip placement based on direction
|
|
9
|
-
* - Event handlers for mouse and keyboard interactions (hover, focus)
|
|
10
|
-
* - Viewport boundary detection to keep tooltips visible
|
|
11
|
-
* - Delay handling for show/hide animations
|
|
12
|
-
* - Popover API integration for native browser tooltip behavior
|
|
13
|
-
*
|
|
14
|
-
* This component should only be used when the tooltip is enabled and has content.
|
|
15
|
-
* For disabled tooltips, use the main Tooltip component which returns early.
|
|
16
|
-
*/
|
|
17
|
-
const TooltipBase = ({ className, contentClassName, children, content, delay = 0, direction = 'top', blur = false, }) => {
|
|
18
|
-
const triggerRef = useRef(null);
|
|
19
|
-
const tooltipRef = useRef(null);
|
|
20
|
-
const timeoutRef = useRef();
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
const trigger = triggerRef.current;
|
|
23
|
-
const tooltip = tooltipRef.current;
|
|
24
|
-
if (!trigger || !tooltip)
|
|
25
|
-
return;
|
|
26
|
-
const positionTooltip = () => {
|
|
27
|
-
const rect = trigger.getBoundingClientRect();
|
|
28
|
-
const tooltipRect = tooltip.getBoundingClientRect();
|
|
29
|
-
let top = 0;
|
|
30
|
-
let left = 0;
|
|
31
|
-
switch (direction) {
|
|
32
|
-
case 'top':
|
|
33
|
-
top = rect.top - tooltipRect.height - 8;
|
|
34
|
-
left = rect.left + rect.width / 2 - tooltipRect.width / 2;
|
|
35
|
-
break;
|
|
36
|
-
case 'bottom':
|
|
37
|
-
top = rect.bottom + 8;
|
|
38
|
-
left = rect.left + rect.width / 2 - tooltipRect.width / 2;
|
|
39
|
-
break;
|
|
40
|
-
case 'left':
|
|
41
|
-
top = rect.top + rect.height / 2 - tooltipRect.height / 2;
|
|
42
|
-
left = rect.left - tooltipRect.width - 8;
|
|
43
|
-
break;
|
|
44
|
-
case 'right':
|
|
45
|
-
top = rect.top + rect.height / 2 - tooltipRect.height / 2;
|
|
46
|
-
left = rect.right + 8;
|
|
47
|
-
break;
|
|
48
|
-
}
|
|
49
|
-
// Ensure tooltip stays within viewport
|
|
50
|
-
const padding = 10;
|
|
51
|
-
left = Math.max(padding, Math.min(left, window.innerWidth - tooltipRect.width - padding));
|
|
52
|
-
top = Math.max(padding, Math.min(top, window.innerHeight - tooltipRect.height - padding));
|
|
53
|
-
tooltip.style.left = `${left}px`;
|
|
54
|
-
tooltip.style.top = `${top}px`;
|
|
55
|
-
};
|
|
56
|
-
const showTooltip = () => {
|
|
57
|
-
timeoutRef.current = window.setTimeout(() => {
|
|
58
|
-
tooltip.showPopover?.();
|
|
59
|
-
positionTooltip();
|
|
60
|
-
}, delay);
|
|
61
|
-
};
|
|
62
|
-
const hideTooltip = () => {
|
|
63
|
-
clearTimeout(timeoutRef.current);
|
|
64
|
-
tooltip.hidePopover?.();
|
|
65
|
-
};
|
|
66
|
-
trigger.addEventListener('mouseenter', showTooltip);
|
|
67
|
-
trigger.addEventListener('mouseleave', hideTooltip);
|
|
68
|
-
trigger.addEventListener('focus', showTooltip);
|
|
69
|
-
trigger.addEventListener('blur', hideTooltip);
|
|
70
|
-
return () => {
|
|
71
|
-
clearTimeout(timeoutRef.current);
|
|
72
|
-
trigger.removeEventListener('mouseenter', showTooltip);
|
|
73
|
-
trigger.removeEventListener('mouseleave', hideTooltip);
|
|
74
|
-
trigger.removeEventListener('focus', showTooltip);
|
|
75
|
-
trigger.removeEventListener('blur', hideTooltip);
|
|
76
|
-
};
|
|
77
|
-
}, [content, delay, direction]);
|
|
78
|
-
return (jsxs(Fragment, { children: [jsx("div", { ref: triggerRef, className: cn(S.trigger, className), children: children }), jsx("div", { ref: tooltipRef, popover: "manual", className: cn(S.tooltip, blur && S.blur, contentClassName), "data-direction": direction, children: content })] }));
|
|
79
|
-
};
|
|
80
|
-
const Tooltip = ({ className, contentClassName, children, content, delay = 0, direction = 'top', blur = false, disabled = false, }) => {
|
|
5
|
+
const LazyTooltipOverTrigger = lazy(() => import('./TooltipOverTrigger.js'));
|
|
6
|
+
const Tooltip = ({ className, contentClassName, children, content, delay = 0, direction = 'top', blur = false, disabled = false, overTrigger = false, }) => {
|
|
81
7
|
if (disabled || !content)
|
|
82
8
|
return jsx(Fragment, { children: children });
|
|
83
|
-
|
|
9
|
+
if (overTrigger) {
|
|
10
|
+
return (jsx(Suspense, { fallback: jsx(Fragment, { children: children }), children: jsx(LazyTooltipOverTrigger, { className: className, contentClassName: contentClassName, content: content, delay: delay, direction: direction, blur: blur, children: children }) }));
|
|
11
|
+
}
|
|
12
|
+
return (jsx(TooltipSimple, { className: className, contentClassName: contentClassName, content: content, delay: delay, direction: direction, blur: blur, children: children }));
|
|
84
13
|
};
|
|
85
14
|
|
|
86
15
|
export { Tooltip };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import styleInject from '../../../node_modules/style-inject/dist/style-inject.es.js';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".Tooltip_trigger__9GSNV{display:inline-block}.Tooltip_tooltip__tzL8q{word-wrap:break-word;background:var(--decent-color-alpha-900);border-radius:4px;box-shadow:0 0 0 1px var(--accent-color-alpha-100);color:var(--accent-color);font-size:14px;line-height:1.4;margin:0;max-width:250px;padding:6px 12px;pointer-events:none;position:fixed;z-index:9999}.Tooltip_tooltip__tzL8q.Tooltip_blur__SQYHW{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:var(--decent-color-alpha-500)}.Tooltip_tooltip__tzL8q:after{content:\"\";position:absolute}.Tooltip_tooltip__tzL8q[data-direction=top]{transform:translateY(0)}.Tooltip_tooltip__tzL8q[data-direction=top]:after{left:50%;top:100%;transform:translateX(-50%)}.Tooltip_tooltip__tzL8q[data-direction=bottom]{transform:translateY(0)}.Tooltip_tooltip__tzL8q[data-direction=bottom]:after{bottom:100%;left:50%;transform:translateX(-50%)}.Tooltip_tooltip__tzL8q[data-direction=left]{transform:translateX(0)}.Tooltip_tooltip__tzL8q[data-direction=left]:after{left:100%;top:50%;transform:translateY(-50%)}.Tooltip_tooltip__tzL8q[data-direction=right]{transform:translateX(0)}.Tooltip_tooltip__tzL8q[data-direction=right]:after{right:100%;top:50%;transform:translateY(-50%)}.Tooltip_tooltip__tzL8q:popover-open{animation:Tooltip_fadeIn__Buhx4 .2s ease-out}@keyframes Tooltip_fadeIn__Buhx4{0%{opacity:0}to{opacity:1}}";
|
|
4
|
-
var S = {"trigger":"Tooltip_trigger__9GSNV","tooltip":"Tooltip_tooltip__tzL8q","blur":"Tooltip_blur__SQYHW","fadeIn":"Tooltip_fadeIn__Buhx4"};
|
|
3
|
+
var css_248z = ".Tooltip_trigger__9GSNV{display:inline-block}.Tooltip_tooltip__tzL8q{word-wrap:break-word;background:var(--decent-color-alpha-900);border-radius:4px;box-shadow:0 0 0 1px var(--accent-color-alpha-100);color:var(--accent-color);font-size:14px;line-height:1.4;margin:0;max-width:250px;padding:6px 12px;pointer-events:none;position:fixed;z-index:9999}.Tooltip_tooltip__tzL8q.Tooltip_blur__SQYHW{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:var(--decent-color-alpha-500)}.Tooltip_tooltip__tzL8q:after{content:\"\";position:absolute}.Tooltip_tooltip__tzL8q[data-direction=top]{transform:translateY(0)}.Tooltip_tooltip__tzL8q[data-direction=top]:after{left:50%;top:100%;transform:translateX(-50%)}.Tooltip_tooltip__tzL8q[data-direction=bottom]{transform:translateY(0)}.Tooltip_tooltip__tzL8q[data-direction=bottom]:after{bottom:100%;left:50%;transform:translateX(-50%)}.Tooltip_tooltip__tzL8q[data-direction=left]{transform:translateX(0)}.Tooltip_tooltip__tzL8q[data-direction=left]:after{left:100%;top:50%;transform:translateY(-50%)}.Tooltip_tooltip__tzL8q[data-direction=right]{transform:translateX(0)}.Tooltip_tooltip__tzL8q[data-direction=right]:after{right:100%;top:50%;transform:translateY(-50%)}.Tooltip_tooltip__tzL8q:popover-open{animation:Tooltip_fadeIn__Buhx4 .2s ease-out}.Tooltip_tooltip__tzL8q.Tooltip_tooltipOverTrigger__gRUoT{word-wrap:break-word;box-sizing:border-box;height:-moz-fit-content;height:fit-content;max-width:none;overflow-wrap:break-word;white-space:normal}.Tooltip_tooltip__tzL8q.Tooltip_tooltipOverTrigger__gRUoT:after{display:none}.Tooltip_tooltip__tzL8q.Tooltip_tooltipOverTrigger__gRUoT:popover-open{animation:Tooltip_fadeIn__Buhx4 .15s ease-out}@keyframes Tooltip_fadeIn__Buhx4{0%{opacity:0}to{opacity:1}}";
|
|
4
|
+
var S = {"trigger":"Tooltip_trigger__9GSNV","tooltip":"Tooltip_tooltip__tzL8q","blur":"Tooltip_blur__SQYHW","fadeIn":"Tooltip_fadeIn__Buhx4","tooltipOverTrigger":"Tooltip_tooltipOverTrigger__gRUoT"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
7
7
|
export { S as default };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import S from './Tooltip.styl.js';
|
|
4
|
+
import cn from 'classnames';
|
|
5
|
+
|
|
6
|
+
const TooltipCore = ({ className, contentClassName, children, content, delay = 0, direction = 'top', blur = false, tooltipExtraClass, dataDirection = direction, usePositionSetup, }) => {
|
|
7
|
+
const triggerRef = useRef(null);
|
|
8
|
+
const tooltipRef = useRef(null);
|
|
9
|
+
usePositionSetup({
|
|
10
|
+
triggerRef,
|
|
11
|
+
tooltipRef,
|
|
12
|
+
content,
|
|
13
|
+
delay,
|
|
14
|
+
direction,
|
|
15
|
+
});
|
|
16
|
+
return (jsxs(Fragment, { children: [jsx("div", { ref: triggerRef, className: cn(S.trigger, className), children: children }), jsx("div", { ref: tooltipRef, popover: "manual", className: cn(S.tooltip, blur && S.blur, tooltipExtraClass, contentClassName), "data-direction": dataDirection, children: content })] }));
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { TooltipCore };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useCallback, useLayoutEffect, useEffect } from 'react';
|
|
3
|
+
import S from './Tooltip.styl.js';
|
|
4
|
+
import { TooltipCore } from './TooltipCore.js';
|
|
5
|
+
import { applyTriggerTextStyles, getTextStyleSource, clearTriggerTextStyles } from './tooltipTextStyles.js';
|
|
6
|
+
|
|
7
|
+
function parsePx(value) {
|
|
8
|
+
return Number.parseFloat(value) || 0;
|
|
9
|
+
}
|
|
10
|
+
function applyOverTriggerStyles(contentEl, triggerEl) {
|
|
11
|
+
const rect = triggerEl.getBoundingClientRect();
|
|
12
|
+
const contentComputed = window.getComputedStyle(contentEl);
|
|
13
|
+
const paddingLeft = parsePx(contentComputed.paddingLeft);
|
|
14
|
+
const paddingRight = parsePx(contentComputed.paddingRight);
|
|
15
|
+
const paddingTop = parsePx(contentComputed.paddingTop);
|
|
16
|
+
const borderLeft = parsePx(contentComputed.borderLeftWidth);
|
|
17
|
+
const borderRight = parsePx(contentComputed.borderRightWidth);
|
|
18
|
+
const borderTop = parsePx(contentComputed.borderTopWidth);
|
|
19
|
+
contentEl.style.setProperty('left', `${rect.left - paddingLeft - borderLeft}px`);
|
|
20
|
+
contentEl.style.setProperty('top', `${rect.top - paddingTop - borderTop}px`);
|
|
21
|
+
contentEl.style.setProperty('transform', 'none');
|
|
22
|
+
contentEl.style.width = `${rect.width + paddingLeft + paddingRight + borderLeft + borderRight}px`;
|
|
23
|
+
contentEl.style.boxSizing = 'border-box';
|
|
24
|
+
applyTriggerTextStyles(contentEl, getTextStyleSource(triggerEl));
|
|
25
|
+
// Trigger ancestors (e.g. menu items) often use nowrap for ellipsis; allow wrap here.
|
|
26
|
+
contentEl.style.setProperty('white-space', 'normal');
|
|
27
|
+
contentEl.style.setProperty('overflow-wrap', 'break-word');
|
|
28
|
+
}
|
|
29
|
+
function clearOverTriggerStyles(contentEl) {
|
|
30
|
+
if (!contentEl)
|
|
31
|
+
return;
|
|
32
|
+
contentEl.style.removeProperty('left');
|
|
33
|
+
contentEl.style.removeProperty('top');
|
|
34
|
+
contentEl.style.removeProperty('transform');
|
|
35
|
+
contentEl.style.removeProperty('width');
|
|
36
|
+
contentEl.style.removeProperty('box-sizing');
|
|
37
|
+
contentEl.style.removeProperty('white-space');
|
|
38
|
+
contentEl.style.removeProperty('overflow-wrap');
|
|
39
|
+
clearTriggerTextStyles(contentEl);
|
|
40
|
+
}
|
|
41
|
+
const useOverTriggerPositionSetup = ({ triggerRef, tooltipRef, content, delay, }) => {
|
|
42
|
+
const timeoutRef = useRef();
|
|
43
|
+
const updateOverTriggerPosition = useCallback(() => {
|
|
44
|
+
const triggerEl = triggerRef.current;
|
|
45
|
+
const contentEl = tooltipRef.current;
|
|
46
|
+
if (!triggerEl || !contentEl)
|
|
47
|
+
return;
|
|
48
|
+
applyOverTriggerStyles(contentEl, triggerEl);
|
|
49
|
+
}, [tooltipRef, triggerRef]);
|
|
50
|
+
useLayoutEffect(() => {
|
|
51
|
+
let frameId = 0;
|
|
52
|
+
const tick = () => {
|
|
53
|
+
updateOverTriggerPosition();
|
|
54
|
+
frameId = requestAnimationFrame(tick);
|
|
55
|
+
};
|
|
56
|
+
tick();
|
|
57
|
+
window.addEventListener('scroll', updateOverTriggerPosition, true);
|
|
58
|
+
window.addEventListener('resize', updateOverTriggerPosition);
|
|
59
|
+
return () => {
|
|
60
|
+
cancelAnimationFrame(frameId);
|
|
61
|
+
window.removeEventListener('scroll', updateOverTriggerPosition, true);
|
|
62
|
+
window.removeEventListener('resize', updateOverTriggerPosition);
|
|
63
|
+
clearOverTriggerStyles(tooltipRef.current);
|
|
64
|
+
};
|
|
65
|
+
}, [tooltipRef, updateOverTriggerPosition]);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
const trigger = triggerRef.current;
|
|
68
|
+
const tooltip = tooltipRef.current;
|
|
69
|
+
if (!trigger || !tooltip)
|
|
70
|
+
return;
|
|
71
|
+
const showTooltip = () => {
|
|
72
|
+
timeoutRef.current = window.setTimeout(() => {
|
|
73
|
+
tooltip.showPopover?.();
|
|
74
|
+
updateOverTriggerPosition();
|
|
75
|
+
}, delay);
|
|
76
|
+
};
|
|
77
|
+
const hideTooltip = () => {
|
|
78
|
+
clearTimeout(timeoutRef.current);
|
|
79
|
+
tooltip.hidePopover?.();
|
|
80
|
+
};
|
|
81
|
+
trigger.addEventListener('mouseenter', showTooltip);
|
|
82
|
+
trigger.addEventListener('mouseleave', hideTooltip);
|
|
83
|
+
trigger.addEventListener('focus', showTooltip);
|
|
84
|
+
trigger.addEventListener('blur', hideTooltip);
|
|
85
|
+
return () => {
|
|
86
|
+
clearTimeout(timeoutRef.current);
|
|
87
|
+
trigger.removeEventListener('mouseenter', showTooltip);
|
|
88
|
+
trigger.removeEventListener('mouseleave', hideTooltip);
|
|
89
|
+
trigger.removeEventListener('focus', showTooltip);
|
|
90
|
+
trigger.removeEventListener('blur', hideTooltip);
|
|
91
|
+
};
|
|
92
|
+
}, [content, delay, tooltipRef, triggerRef, updateOverTriggerPosition]);
|
|
93
|
+
};
|
|
94
|
+
const TooltipOverTrigger = (props) => (jsx(TooltipCore, { usePositionSetup: useOverTriggerPositionSetup, tooltipExtraClass: S.tooltipOverTrigger, dataDirection: undefined, ...props }));
|
|
95
|
+
|
|
96
|
+
export { TooltipOverTrigger as default };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useEffect } from 'react';
|
|
3
|
+
import { TooltipCore } from './TooltipCore.js';
|
|
4
|
+
import { clearTriggerTextStyles, applyTriggerTextStyles, getTextStyleSource } from './tooltipTextStyles.js';
|
|
5
|
+
|
|
6
|
+
const useSimplePositionSetup = ({ triggerRef, tooltipRef, content, delay, direction, }) => {
|
|
7
|
+
const timeoutRef = useRef();
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const trigger = triggerRef.current;
|
|
10
|
+
const tooltip = tooltipRef.current;
|
|
11
|
+
if (!trigger || !tooltip)
|
|
12
|
+
return;
|
|
13
|
+
const positionTooltip = () => {
|
|
14
|
+
const rect = trigger.getBoundingClientRect();
|
|
15
|
+
const tooltipRect = tooltip.getBoundingClientRect();
|
|
16
|
+
let top = 0;
|
|
17
|
+
let left = 0;
|
|
18
|
+
switch (direction) {
|
|
19
|
+
case 'top':
|
|
20
|
+
top = rect.top - tooltipRect.height - 8;
|
|
21
|
+
left = rect.left + rect.width / 2 - tooltipRect.width / 2;
|
|
22
|
+
break;
|
|
23
|
+
case 'bottom':
|
|
24
|
+
top = rect.bottom + 8;
|
|
25
|
+
left = rect.left + rect.width / 2 - tooltipRect.width / 2;
|
|
26
|
+
break;
|
|
27
|
+
case 'left':
|
|
28
|
+
top = rect.top + rect.height / 2 - tooltipRect.height / 2;
|
|
29
|
+
left = rect.left - tooltipRect.width - 8;
|
|
30
|
+
break;
|
|
31
|
+
case 'right':
|
|
32
|
+
top = rect.top + rect.height / 2 - tooltipRect.height / 2;
|
|
33
|
+
left = rect.right + 8;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
const padding = 10;
|
|
37
|
+
left = Math.max(padding, Math.min(left, window.innerWidth - tooltipRect.width - padding));
|
|
38
|
+
top = Math.max(padding, Math.min(top, window.innerHeight - tooltipRect.height - padding));
|
|
39
|
+
tooltip.style.left = `${left}px`;
|
|
40
|
+
tooltip.style.top = `${top}px`;
|
|
41
|
+
};
|
|
42
|
+
const showTooltip = () => {
|
|
43
|
+
timeoutRef.current = window.setTimeout(() => {
|
|
44
|
+
applyTriggerTextStyles(tooltip, getTextStyleSource(trigger));
|
|
45
|
+
tooltip.showPopover?.();
|
|
46
|
+
positionTooltip();
|
|
47
|
+
}, delay);
|
|
48
|
+
};
|
|
49
|
+
const hideTooltip = () => {
|
|
50
|
+
clearTimeout(timeoutRef.current);
|
|
51
|
+
tooltip.hidePopover?.();
|
|
52
|
+
clearTriggerTextStyles(tooltip);
|
|
53
|
+
};
|
|
54
|
+
trigger.addEventListener('mouseenter', showTooltip);
|
|
55
|
+
trigger.addEventListener('mouseleave', hideTooltip);
|
|
56
|
+
trigger.addEventListener('focus', showTooltip);
|
|
57
|
+
trigger.addEventListener('blur', hideTooltip);
|
|
58
|
+
return () => {
|
|
59
|
+
clearTimeout(timeoutRef.current);
|
|
60
|
+
clearTriggerTextStyles(tooltip);
|
|
61
|
+
trigger.removeEventListener('mouseenter', showTooltip);
|
|
62
|
+
trigger.removeEventListener('mouseleave', hideTooltip);
|
|
63
|
+
trigger.removeEventListener('focus', showTooltip);
|
|
64
|
+
trigger.removeEventListener('blur', hideTooltip);
|
|
65
|
+
};
|
|
66
|
+
}, [content, delay, direction, tooltipRef, triggerRef]);
|
|
67
|
+
};
|
|
68
|
+
const TooltipSimple = (props) => jsx(TooltipCore, { usePositionSetup: useSimplePositionSetup, ...props });
|
|
69
|
+
|
|
70
|
+
export { TooltipSimple };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const TRIGGER_TEXT_STYLE_PROPS = [
|
|
2
|
+
'font-family',
|
|
3
|
+
'font-size',
|
|
4
|
+
'font-weight',
|
|
5
|
+
'font-style',
|
|
6
|
+
'font-variant',
|
|
7
|
+
'font-stretch',
|
|
8
|
+
'line-height',
|
|
9
|
+
'letter-spacing',
|
|
10
|
+
'word-spacing',
|
|
11
|
+
'text-transform',
|
|
12
|
+
'text-indent',
|
|
13
|
+
'text-decoration-line',
|
|
14
|
+
'text-decoration-color',
|
|
15
|
+
'text-decoration-style',
|
|
16
|
+
'text-decoration-thickness',
|
|
17
|
+
'text-underline-offset',
|
|
18
|
+
'font-feature-settings',
|
|
19
|
+
'font-variation-settings',
|
|
20
|
+
'font-kerning',
|
|
21
|
+
'font-optical-sizing',
|
|
22
|
+
'font-synthesis',
|
|
23
|
+
'font-variant-numeric',
|
|
24
|
+
'font-variant-ligatures',
|
|
25
|
+
'font-variant-caps',
|
|
26
|
+
'font-variant-east-asian',
|
|
27
|
+
'tab-size',
|
|
28
|
+
'color',
|
|
29
|
+
'word-break',
|
|
30
|
+
'overflow-wrap',
|
|
31
|
+
'hyphens',
|
|
32
|
+
];
|
|
33
|
+
function getTextStyleSource(triggerEl) {
|
|
34
|
+
const firstChild = triggerEl.firstElementChild;
|
|
35
|
+
return firstChild instanceof HTMLElement ? firstChild : triggerEl;
|
|
36
|
+
}
|
|
37
|
+
function applyTriggerTextStyles(contentEl, sourceEl) {
|
|
38
|
+
const computed = window.getComputedStyle(sourceEl);
|
|
39
|
+
for (const prop of TRIGGER_TEXT_STYLE_PROPS) {
|
|
40
|
+
contentEl.style.setProperty(prop, computed.getPropertyValue(prop));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function clearTriggerTextStyles(contentEl) {
|
|
44
|
+
for (const prop of TRIGGER_TEXT_STYLE_PROPS) {
|
|
45
|
+
contentEl.style.removeProperty(prop);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { TRIGGER_TEXT_STYLE_PROPS, applyTriggerTextStyles, clearTriggerTextStyles, getTextStyleSource };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
|
+
export type TooltipSide = 'top' | 'bottom' | 'left' | 'right';
|
|
3
|
+
export type Props = HTMLAttributes<HTMLDivElement> & {
|
|
4
|
+
width?: number;
|
|
5
|
+
maxWidth?: number;
|
|
6
|
+
side?: TooltipSide;
|
|
7
|
+
overTrigger?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type TextWithDeferTooltipProps = Props;
|
|
@@ -8,10 +8,11 @@ export interface TooltipProps {
|
|
|
8
8
|
direction?: 'top' | 'bottom' | 'left' | 'right';
|
|
9
9
|
blur?: boolean;
|
|
10
10
|
disabled?: boolean;
|
|
11
|
+
overTrigger?: boolean;
|
|
11
12
|
}
|
|
12
13
|
declare module 'react' {
|
|
13
14
|
interface HTMLAttributes<T> {
|
|
14
15
|
popover?: string;
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
|
-
export declare const Tooltip: ({ className, contentClassName, children, content, delay, direction, blur, disabled, }: TooltipProps) => JSX.Element;
|
|
18
|
+
export declare const Tooltip: ({ className, contentClassName, children, content, delay, direction, blur, disabled, overTrigger, }: TooltipProps) => JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/// <reference types="uilib/components/tooltip/types" />
|
|
2
|
+
export interface TooltipPositionSetupOptions {
|
|
3
|
+
triggerRef: React.RefObject<HTMLDivElement | null>;
|
|
4
|
+
tooltipRef: React.RefObject<HTMLDivElement | null>;
|
|
5
|
+
content?: React.ReactNode;
|
|
6
|
+
delay: number;
|
|
7
|
+
direction: 'top' | 'bottom' | 'left' | 'right';
|
|
8
|
+
}
|
|
9
|
+
export interface TooltipCoreProps {
|
|
10
|
+
className?: string;
|
|
11
|
+
contentClassName?: string;
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
content?: React.ReactNode;
|
|
14
|
+
delay?: number;
|
|
15
|
+
direction?: 'top' | 'bottom' | 'left' | 'right';
|
|
16
|
+
blur?: boolean;
|
|
17
|
+
tooltipExtraClass?: string;
|
|
18
|
+
dataDirection?: 'top' | 'bottom' | 'left' | 'right';
|
|
19
|
+
usePositionSetup: (options: TooltipPositionSetupOptions) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare const TooltipCore: ({ className, contentClassName, children, content, delay, direction, blur, tooltipExtraClass, dataDirection, usePositionSetup, }: TooltipCoreProps) => JSX.Element;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const TRIGGER_TEXT_STYLE_PROPS: readonly ["font-family", "font-size", "font-weight", "font-style", "font-variant", "font-stretch", "line-height", "letter-spacing", "word-spacing", "text-transform", "text-indent", "text-decoration-line", "text-decoration-color", "text-decoration-style", "text-decoration-thickness", "text-underline-offset", "font-feature-settings", "font-variation-settings", "font-kerning", "font-optical-sizing", "font-synthesis", "font-variant-numeric", "font-variant-ligatures", "font-variant-caps", "font-variant-east-asian", "tab-size", "color", "word-break", "overflow-wrap", "hyphens"];
|
|
2
|
+
export declare function getTextStyleSource(triggerEl: HTMLElement): HTMLElement;
|
|
3
|
+
export declare function applyTriggerTextStyles(contentEl: HTMLElement, sourceEl: HTMLElement): void;
|
|
4
|
+
export declare function clearTriggerTextStyles(contentEl: HTMLElement): void;
|
|
@@ -47,6 +47,7 @@ export * from './Spinner/Spinner';
|
|
|
47
47
|
export * from './Table/Table';
|
|
48
48
|
export * from './Tabs/Tabs';
|
|
49
49
|
export * from './TextShimmer/TextShimmer';
|
|
50
|
+
export * from './TextWithDeferTooltip';
|
|
50
51
|
export * from './Tooltip/Tooltip';
|
|
51
52
|
export * from './Text/Text';
|
|
52
53
|
export * from './Theme/Theme';
|
|
@@ -171,49 +171,33 @@
|
|
|
171
171
|
"169": "Community 169",
|
|
172
172
|
"170": "Community 170",
|
|
173
173
|
"171": "Community 171",
|
|
174
|
-
"172": "Community 172",
|
|
175
174
|
"173": "Community 173",
|
|
176
|
-
"174": "Community 174",
|
|
177
175
|
"175": "Community 175",
|
|
178
176
|
"176": "Community 176",
|
|
179
|
-
"177": "Community 177",
|
|
180
|
-
"178": "Community 178",
|
|
181
177
|
"179": "Community 179",
|
|
182
178
|
"180": "Community 180",
|
|
183
|
-
"181": "Community 181",
|
|
184
179
|
"182": "Community 182",
|
|
185
180
|
"183": "Community 183",
|
|
186
181
|
"184": "Community 184",
|
|
187
|
-
"185": "Community 185",
|
|
188
|
-
"186": "Community 186",
|
|
189
182
|
"187": "Community 187",
|
|
190
183
|
"188": "Community 188",
|
|
191
184
|
"189": "Community 189",
|
|
192
|
-
"190": "Community 190",
|
|
193
|
-
"191": "Community 191",
|
|
194
185
|
"192": "Community 192",
|
|
195
|
-
"193": "Community 193",
|
|
196
186
|
"194": "Community 194",
|
|
197
187
|
"195": "Community 195",
|
|
198
|
-
"196": "Community 196",
|
|
199
188
|
"197": "Community 197",
|
|
200
189
|
"198": "Community 198",
|
|
201
190
|
"199": "Community 199",
|
|
202
191
|
"200": "Community 200",
|
|
203
192
|
"201": "Community 201",
|
|
204
193
|
"202": "Community 202",
|
|
205
|
-
"203": "Community 203",
|
|
206
194
|
"204": "Community 204",
|
|
207
195
|
"205": "Community 205",
|
|
208
|
-
"206": "Community 206",
|
|
209
196
|
"207": "Community 207",
|
|
210
|
-
"208": "Community 208",
|
|
211
|
-
"209": "Community 209",
|
|
212
197
|
"210": "Community 210",
|
|
213
198
|
"211": "Community 211",
|
|
214
199
|
"212": "Community 212",
|
|
215
200
|
"213": "Community 213",
|
|
216
|
-
"214": "Community 214",
|
|
217
201
|
"215": "Community 215",
|
|
218
202
|
"216": "Community 216"
|
|
219
203
|
}
|