@redocly/theme 0.62.0-next.6 → 0.62.0-next.7
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/components/Breadcrumbs/Breadcrumb.js +1 -1
- package/lib/components/Breadcrumbs/BreadcrumbDropdown.js +1 -1
- package/lib/components/Catalog/CatalogTagsWithTooltip.js +1 -1
- package/lib/components/CodeBlock/CodeBlockControls.js +5 -5
- package/lib/components/Tooltip/Tooltip.d.ts +2 -3
- package/lib/components/Tooltip/Tooltip.js +66 -113
- package/lib/components/Tooltip/variables.dark.js +4 -0
- package/lib/components/Tooltip/variables.js +3 -3
- package/lib/core/hooks/use-outside-click.d.ts +3 -1
- package/lib/core/hooks/use-outside-click.js +8 -4
- package/package.json +4 -4
- package/src/components/Breadcrumbs/Breadcrumb.tsx +3 -3
- package/src/components/Breadcrumbs/BreadcrumbDropdown.tsx +3 -3
- package/src/components/Catalog/CatalogTagsWithTooltip.tsx +3 -3
- package/src/components/CodeBlock/CodeBlockControls.tsx +13 -9
- package/src/components/Tooltip/Tooltip.tsx +77 -120
- package/src/components/Tooltip/variables.dark.ts +4 -0
- package/src/components/Tooltip/variables.ts +3 -3
- package/src/core/hooks/use-outside-click.ts +16 -5
- package/lib/components/Tooltip/TooltipWrapper.d.ts +0 -12
- package/lib/components/Tooltip/TooltipWrapper.js +0 -34
- package/src/components/Tooltip/TooltipWrapper.tsx +0 -70
|
@@ -51,7 +51,7 @@ function Breadcrumb({ label, link, isActive, onClick, icon }) {
|
|
|
51
51
|
react_1.default.createElement(BreadcrumbIcon_1.BreadcrumbIcon, { icon: icon }),
|
|
52
52
|
displayLabel));
|
|
53
53
|
const breadcrumbContent = link ? (react_1.default.createElement(BreadcrumbLink, { "data-component-name": "Breadcrumbs/BreadcrumbLink", to: link, onClick: onClick, "$isActive": isActive }, content)) : (react_1.default.createElement(BreadcrumbWrapper, { "data-component-name": "Breadcrumbs/BreadcrumbWrapper", "$isActive": isActive, onClick: onClick, tabIndex: -1 }, content));
|
|
54
|
-
return isTruncated ? (react_1.default.createElement(Tooltip_1.
|
|
54
|
+
return isTruncated ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: label, placement: "bottom" }, breadcrumbContent)) : (breadcrumbContent);
|
|
55
55
|
}
|
|
56
56
|
const baseBreadcrumbStyles = `
|
|
57
57
|
display: flex;
|
|
@@ -55,7 +55,7 @@ function BreadcrumbDropdown({ children, label, items, onItemClick, className, })
|
|
|
55
55
|
return null;
|
|
56
56
|
}
|
|
57
57
|
const isTruncated = label.length > constants_1.BREADCRUMB_MAX_LENGTH;
|
|
58
|
-
const triggerContent = isTruncated ? (react_1.default.createElement(Tooltip_1.
|
|
58
|
+
const triggerContent = isTruncated ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: label, placement: "bottom" },
|
|
59
59
|
react_1.default.createElement(TriggerContentWrapper, null, children))) : (children);
|
|
60
60
|
const trigger = react_1.default.createElement(StyledDropdownTrigger, null, triggerContent);
|
|
61
61
|
return (react_1.default.createElement(BreadcrumbDropdownWrapper, { "data-component-name": "Breadcrumbs/BreadcrumbDropdown", className: className, "data-testid": "breadcrumb-dropdown" },
|
|
@@ -27,7 +27,7 @@ function CatalogTagsWithTooltip({ items, itemsToShow = 1, showPlaceholder = true
|
|
|
27
27
|
}
|
|
28
28
|
const displayedItems = items.slice(0, itemsToShow);
|
|
29
29
|
const remainingCount = items.length - itemsToShow;
|
|
30
|
-
return (react_1.default.createElement(Tooltip_1.
|
|
30
|
+
return (react_1.default.createElement(Tooltip_1.Tooltip, { tip: items.join(', '), placement: "bottom", className: "catalog", width: "400px" },
|
|
31
31
|
react_1.default.createElement(CatalogTagsWrapper, { "data-component-name": "Catalog/CatalogTagsWithTooltip" },
|
|
32
32
|
displayedItems.map((item, index) => (react_1.default.createElement(Tag_1.Tag, Object.assign({ key: `${item}-${index}` }, tagProps, { textTransform: "none", maxLength: constants_1.CATALOG_TAG_MAX_LENGTH }),
|
|
33
33
|
react_1.default.createElement(CatalogHighlight_1.CatalogHighlight, null, item)))),
|
|
@@ -8,7 +8,7 @@ const react_1 = __importDefault(require("react"));
|
|
|
8
8
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
9
|
const CodeBlockTabs_1 = require("../../components/CodeBlock/CodeBlockTabs");
|
|
10
10
|
const CopyButton_1 = require("../../components/Buttons/CopyButton");
|
|
11
|
-
const
|
|
11
|
+
const Tooltip_1 = require("../../components/Tooltip/Tooltip");
|
|
12
12
|
const hooks_1 = require("../../core/hooks");
|
|
13
13
|
const DeselectIcon_1 = require("../../icons/DeselectIcon/DeselectIcon");
|
|
14
14
|
const MaximizeIcon_1 = require("../../icons/MaximizeIcon/MaximizeIcon");
|
|
@@ -38,15 +38,15 @@ function CodeBlockControls({ children, className, title, controls, tabs, dropdow
|
|
|
38
38
|
tabs && react_1.default.createElement(CodeBlockTabs_1.CodeBlockTabs, { tabs: tabs }),
|
|
39
39
|
react_1.default.createElement(ControlsWrapper, null,
|
|
40
40
|
dropdown && react_1.default.createElement(CodeBlockDropdown_1.CodeBlockDropdown, Object.assign({}, dropdown)),
|
|
41
|
-
report && !report.hidden && !((_a = report === null || report === void 0 ? void 0 : report.props) === null || _a === void 0 ? void 0 : _a.hide) ? (react_1.default.createElement(
|
|
41
|
+
report && !report.hidden && !((_a = report === null || report === void 0 ? void 0 : report.props) === null || _a === void 0 ? void 0 : _a.hide) ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: translate('codeSnippet.report.tooltipText', 'Report a problem'), placement: "top", arrowPosition: "right" },
|
|
42
42
|
react_1.default.createElement(ControlButton, Object.assign({ variant: "text", size: "small", "data-testid": "report-button", icon: controlsType === 'icon' ? react_1.default.createElement(WarningSquareIcon_1.WarningSquareIcon, { size: "18px" }) : undefined }, report.props), controlsType != 'icon' && (((_b = report.props) === null || _b === void 0 ? void 0 : _b.buttonText) || 'Report')))) : null,
|
|
43
|
-
expand && !((_c = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.expand) === null || _c === void 0 ? void 0 : _c.hide) ? (react_1.default.createElement(
|
|
43
|
+
expand && !((_c = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.expand) === null || _c === void 0 ? void 0 : _c.hide) ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: translate('codeSnippet.expand.tooltipText', 'Expand all'), placement: "top", arrowPosition: "right" },
|
|
44
44
|
react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "expand-all", icon: controlsType === 'icon' ? react_1.default.createElement(MaximizeIcon_1.MaximizeIcon, null) : undefined, onClick: expand === null || expand === void 0 ? void 0 : expand.onClick }, controlsType !== 'icon' && ((expand === null || expand === void 0 ? void 0 : expand.label) || 'Expand all')))) : null,
|
|
45
|
-
collapse && !((_d = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.collapse) === null || _d === void 0 ? void 0 : _d.hide) ? (react_1.default.createElement(
|
|
45
|
+
collapse && !((_d = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.collapse) === null || _d === void 0 ? void 0 : _d.hide) ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: translate('codeSnippet.collapse.tooltipText', 'Collapse all'), placement: "top", arrowPosition: "right" },
|
|
46
46
|
react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "collapse-all", icon: controlsType === 'icon' ? react_1.default.createElement(MinimizeIcon_1.MinimizeIcon, null) : undefined, onClick: collapse === null || collapse === void 0 ? void 0 : collapse.onClick }, controlsType !== 'icon' && ((expand === null || expand === void 0 ? void 0 : expand.label) || 'Collapse all')))) : null,
|
|
47
47
|
select ? (react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "select-all", icon: controlsType === 'icon' ? react_1.default.createElement(SelectIcon_1.SelectIcon, null) : undefined, onClick: select === null || select === void 0 ? void 0 : select.onClick }, controlsType !== 'icon' && (select === null || select === void 0 ? void 0 : select.label) ? select.label : 'Select all')) : null,
|
|
48
48
|
deselect ? (react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "clear-all", icon: controlsType === 'icon' ? react_1.default.createElement(DeselectIcon_1.DeselectIcon, null) : undefined, onClick: deselect === null || deselect === void 0 ? void 0 : deselect.onClick }, controlsType !== 'icon' && (deselect === null || deselect === void 0 ? void 0 : deselect.label) ? deselect.label : 'Clear all')) : null,
|
|
49
|
-
copy && !((_e = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.copy) === null || _e === void 0 ? void 0 : _e.hide) ? (react_1.default.createElement(
|
|
49
|
+
copy && !((_e = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.copy) === null || _e === void 0 ? void 0 : _e.hide) ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: translate('codeSnippet.copy.tooltipText', 'Copy to clipboard'), placement: "top", arrowPosition: "right" },
|
|
50
50
|
react_1.default.createElement(StyledCopyButton, { data: copy.data, "data-source": copy.dataSource, "data-hash": copy.dataHash, type: controlsType, toasterPlacement: copy.toasterPlacement, toasterDuration: copy.toasterDuration, buttonText: copy.label, onCopyClick: () => {
|
|
51
51
|
var _a;
|
|
52
52
|
// If there already is a click handler, events should be handled there, cause they pass additional data
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
3
|
export type TooltipProps = {
|
|
4
4
|
tip: string | ReactNode;
|
|
5
5
|
isOpen?: boolean;
|
|
@@ -9,7 +9,6 @@ export type TooltipProps = {
|
|
|
9
9
|
width?: string;
|
|
10
10
|
dataTestId?: string;
|
|
11
11
|
disabled?: boolean;
|
|
12
|
-
arrowPosition?: '
|
|
12
|
+
arrowPosition?: 'left' | 'right' | 'center';
|
|
13
13
|
};
|
|
14
|
-
export declare function TooltipComponent({ children, isOpen, tip, withArrow, placement, className, width, dataTestId, disabled, arrowPosition, }: PropsWithChildren<TooltipProps>): JSX.Element;
|
|
15
14
|
export declare const Tooltip: React.NamedExoticComponent<React.PropsWithChildren<TooltipProps>>;
|
|
@@ -34,113 +34,58 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.Tooltip = void 0;
|
|
37
|
-
exports.TooltipComponent = TooltipComponent;
|
|
38
37
|
const react_1 = __importStar(require("react"));
|
|
39
38
|
const styled_components_1 = __importStar(require("styled-components"));
|
|
40
39
|
const hooks_1 = require("../../core/hooks");
|
|
41
40
|
const Portal_1 = require("../../components/Portal/Portal");
|
|
42
41
|
function TooltipComponent({ children, isOpen, tip, withArrow = true, placement = 'top', className = 'default', width, dataTestId, disabled = false, arrowPosition = 'center', }) {
|
|
43
|
-
const
|
|
42
|
+
const tooltipWrapperRef = (0, react_1.useRef)(null);
|
|
43
|
+
const tooltipBodyRef = (0, react_1.useRef)(null);
|
|
44
44
|
const { isOpened, handleOpen, handleClose } = (0, hooks_1.useControl)(isOpen);
|
|
45
|
-
const
|
|
46
|
-
(0, hooks_1.useOutsideClick)(
|
|
45
|
+
const anchorName = `--tooltip${(0, react_1.useId)().replace(/:/g, '')}`;
|
|
46
|
+
(0, hooks_1.useOutsideClick)(isOpened ? [tooltipWrapperRef, tooltipBodyRef] : tooltipWrapperRef, handleClose);
|
|
47
47
|
const isControlled = isOpen !== undefined;
|
|
48
|
-
const updateTooltipPosition = (0, react_1.useCallback)(() => {
|
|
49
|
-
if (isOpened && ref.current) {
|
|
50
|
-
const rect = ref.current.getBoundingClientRect();
|
|
51
|
-
let top = 0;
|
|
52
|
-
let left = 0;
|
|
53
|
-
switch (placement) {
|
|
54
|
-
case 'top':
|
|
55
|
-
top = rect.top;
|
|
56
|
-
if (arrowPosition === 'left') {
|
|
57
|
-
left = rect.left - 24;
|
|
58
|
-
}
|
|
59
|
-
else if (arrowPosition === 'right') {
|
|
60
|
-
left = rect.right + 24;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
left = rect.left + rect.width / 2;
|
|
64
|
-
}
|
|
65
|
-
break;
|
|
66
|
-
case 'bottom':
|
|
67
|
-
top = rect.bottom;
|
|
68
|
-
if (arrowPosition === 'left') {
|
|
69
|
-
left = rect.left - 24;
|
|
70
|
-
}
|
|
71
|
-
else if (arrowPosition === 'right') {
|
|
72
|
-
left = rect.right + 24;
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
left = rect.left + rect.width / 2;
|
|
76
|
-
}
|
|
77
|
-
break;
|
|
78
|
-
case 'left':
|
|
79
|
-
top = rect.top + rect.height / 2;
|
|
80
|
-
left = rect.left;
|
|
81
|
-
break;
|
|
82
|
-
case 'right':
|
|
83
|
-
top = rect.top + rect.height / 2;
|
|
84
|
-
left = rect.right;
|
|
85
|
-
break;
|
|
86
|
-
}
|
|
87
|
-
setTooltipPosition({ top, left });
|
|
88
|
-
}
|
|
89
|
-
}, [isOpened, placement, arrowPosition]);
|
|
90
|
-
(0, react_1.useEffect)(() => {
|
|
91
|
-
if (isOpened && ref.current) {
|
|
92
|
-
updateTooltipPosition();
|
|
93
|
-
const handleScroll = () => updateTooltipPosition();
|
|
94
|
-
const handleResize = () => updateTooltipPosition();
|
|
95
|
-
window.addEventListener('scroll', handleScroll, true);
|
|
96
|
-
window.addEventListener('resize', handleResize);
|
|
97
|
-
return () => {
|
|
98
|
-
window.removeEventListener('scroll', handleScroll, true);
|
|
99
|
-
window.removeEventListener('resize', handleResize);
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
}, [isOpened, placement, updateTooltipPosition]);
|
|
103
48
|
(0, react_1.useEffect)(() => {
|
|
49
|
+
if (!isControlled)
|
|
50
|
+
return;
|
|
104
51
|
if (isOpen && !disabled) {
|
|
105
52
|
handleOpen();
|
|
106
53
|
}
|
|
107
54
|
else {
|
|
108
55
|
handleClose();
|
|
109
56
|
}
|
|
110
|
-
}, [isOpen, handleOpen, handleClose
|
|
111
|
-
const controllers = !isControlled &&
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
57
|
+
}, [isOpen, disabled, isControlled, handleOpen, handleClose]);
|
|
58
|
+
const controllers = !isControlled && !disabled
|
|
59
|
+
? {
|
|
60
|
+
onMouseEnter: handleOpen,
|
|
61
|
+
onMouseLeave: handleClose,
|
|
62
|
+
onClick: handleClose,
|
|
63
|
+
onFocus: handleOpen,
|
|
64
|
+
onBlur: handleClose,
|
|
65
|
+
}
|
|
66
|
+
: {};
|
|
67
|
+
return (react_1.default.createElement(TooltipWrapper, Object.assign({ ref: tooltipWrapperRef }, controllers, { className: `tooltip-${className}`, "data-component-name": "Tooltip/Tooltip", anchorName: anchorName }),
|
|
120
68
|
children,
|
|
121
69
|
isOpened && !disabled && (react_1.default.createElement(Portal_1.Portal, null,
|
|
122
|
-
react_1.default.createElement(TooltipBody, { "data-testid": dataTestId || (typeof tip === 'string' ? tip : ''), placement: placement, width: width, withArrow: withArrow, arrowPosition: arrowPosition,
|
|
123
|
-
position: 'fixed',
|
|
124
|
-
top: tooltipPosition.top,
|
|
125
|
-
left: tooltipPosition.left,
|
|
126
|
-
} }, tip)))));
|
|
70
|
+
react_1.default.createElement(TooltipBody, { ref: tooltipBodyRef, "data-testid": dataTestId || (typeof tip === 'string' ? tip : ''), placement: placement, width: width, withArrow: withArrow, arrowPosition: arrowPosition, anchorName: anchorName }, tip)))));
|
|
127
71
|
}
|
|
128
72
|
exports.Tooltip = (0, react_1.memo)(TooltipComponent);
|
|
129
73
|
const PLACEMENTS = {
|
|
130
74
|
top: (0, styled_components_1.css) `
|
|
75
|
+
bottom: anchor(top);
|
|
131
76
|
${({ withArrow, arrowPosition }) => withArrow && arrowPosition === 'left'
|
|
132
77
|
? (0, styled_components_1.css) `
|
|
133
|
-
transform: translate(
|
|
134
|
-
|
|
78
|
+
transform: translate(-32px, -6px);
|
|
79
|
+
left: anchor(center);
|
|
135
80
|
`
|
|
136
81
|
: arrowPosition === 'right'
|
|
137
82
|
? (0, styled_components_1.css) `
|
|
138
|
-
transform: translate(
|
|
139
|
-
|
|
83
|
+
transform: translate(32px, -6px);
|
|
84
|
+
right: anchor(center);
|
|
140
85
|
`
|
|
141
86
|
: (0, styled_components_1.css) `
|
|
142
|
-
transform: translate(-50%, -
|
|
143
|
-
|
|
87
|
+
transform: translate(-50%, -6px);
|
|
88
|
+
left: anchor(center);
|
|
144
89
|
`}
|
|
145
90
|
|
|
146
91
|
${({ withArrow, arrowPosition }) => withArrow &&
|
|
@@ -152,26 +97,27 @@ const PLACEMENTS = {
|
|
|
152
97
|
border-top-style: solid;
|
|
153
98
|
border-radius: 2px;
|
|
154
99
|
bottom: 0;
|
|
155
|
-
${arrowPosition === 'left' && 'left: 16px; transform: translateY(
|
|
156
|
-
${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%,
|
|
157
|
-
${arrowPosition === 'right' && 'right: 16px; transform: translateY(
|
|
100
|
+
${arrowPosition === 'left' && 'left: 16px; transform: translateY(100%);'}
|
|
101
|
+
${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 100%);'}
|
|
102
|
+
${arrowPosition === 'right' && 'right: 16px; transform: translateY(100%);'}
|
|
158
103
|
}
|
|
159
104
|
`}
|
|
160
105
|
`,
|
|
161
106
|
bottom: (0, styled_components_1.css) `
|
|
107
|
+
top: anchor(bottom);
|
|
162
108
|
${({ withArrow, arrowPosition }) => withArrow && arrowPosition === 'left'
|
|
163
109
|
? (0, styled_components_1.css) `
|
|
164
|
-
transform: translate(
|
|
165
|
-
|
|
110
|
+
transform: translate(-32px, 6px);
|
|
111
|
+
left: anchor(center);
|
|
166
112
|
`
|
|
167
113
|
: arrowPosition === 'right'
|
|
168
114
|
? (0, styled_components_1.css) `
|
|
169
|
-
transform: translate(
|
|
170
|
-
|
|
115
|
+
transform: translate(32px, 6px);
|
|
116
|
+
right: anchor(center);
|
|
171
117
|
`
|
|
172
118
|
: (0, styled_components_1.css) `
|
|
173
|
-
transform: translate(-50%,
|
|
174
|
-
|
|
119
|
+
transform: translate(-50%, 6px);
|
|
120
|
+
left: anchor(center);
|
|
175
121
|
`}
|
|
176
122
|
|
|
177
123
|
${({ withArrow, arrowPosition }) => withArrow &&
|
|
@@ -183,17 +129,19 @@ const PLACEMENTS = {
|
|
|
183
129
|
border-bottom-style: solid;
|
|
184
130
|
border-radius: 0 0 2px 2px;
|
|
185
131
|
top: 0;
|
|
186
|
-
${arrowPosition === 'left' && 'left: 16px; transform: translateY(-
|
|
187
|
-
${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -
|
|
188
|
-
${arrowPosition === 'right' && 'right: 16px; transform: translateY(-
|
|
132
|
+
${arrowPosition === 'left' && 'left: 16px; transform: translateY(-100%);'}
|
|
133
|
+
${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -100%);'}
|
|
134
|
+
${arrowPosition === 'right' && 'right: 16px; transform: translateY(-100%);'}
|
|
189
135
|
}
|
|
190
136
|
`}
|
|
191
137
|
`,
|
|
192
138
|
left: (0, styled_components_1.css) `
|
|
193
139
|
transform: translate(-100%, -50%);
|
|
194
|
-
margin-left: -
|
|
140
|
+
margin-left: -7px;
|
|
141
|
+
top: anchor(center);
|
|
142
|
+
left: anchor(left);
|
|
195
143
|
|
|
196
|
-
${({ withArrow
|
|
144
|
+
${({ withArrow }) => withArrow &&
|
|
197
145
|
(0, styled_components_1.css) `
|
|
198
146
|
&::after {
|
|
199
147
|
border-top: 14px solid transparent;
|
|
@@ -201,19 +149,19 @@ const PLACEMENTS = {
|
|
|
201
149
|
border-left-width: 8px;
|
|
202
150
|
border-left-style: solid;
|
|
203
151
|
border-radius: 2px 0 0 2px;
|
|
152
|
+
right: -9px;
|
|
204
153
|
top: 50%;
|
|
205
|
-
|
|
206
|
-
${arrowPosition === 'top' && 'top: 16px; transform: translateX(99%);'}
|
|
207
|
-
${arrowPosition === 'center' && 'top: 50%; transform: translate(99%, -50%);'}
|
|
208
|
-
${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(99%);'}
|
|
154
|
+
transform: translateY(-50%);
|
|
209
155
|
}
|
|
210
156
|
`}
|
|
211
157
|
`,
|
|
212
158
|
right: (0, styled_components_1.css) `
|
|
213
159
|
transform: translate(0, -50%);
|
|
214
|
-
margin-left:
|
|
160
|
+
margin-left: 7px;
|
|
161
|
+
top: anchor(center);
|
|
162
|
+
left: anchor(right);
|
|
215
163
|
|
|
216
|
-
${({ withArrow
|
|
164
|
+
${({ withArrow }) => withArrow &&
|
|
217
165
|
(0, styled_components_1.css) `
|
|
218
166
|
&::after {
|
|
219
167
|
border-top: 14px solid transparent;
|
|
@@ -221,28 +169,33 @@ const PLACEMENTS = {
|
|
|
221
169
|
border-right-width: 8px;
|
|
222
170
|
border-right-style: solid;
|
|
223
171
|
border-radius: 0 2px 2px 0;
|
|
172
|
+
left: -9px;
|
|
224
173
|
top: 50%;
|
|
225
|
-
|
|
226
|
-
${arrowPosition === 'top' && 'top: 16px; transform: translateX(-99%);'}
|
|
227
|
-
${arrowPosition === 'center' && 'top: 50%; transform: translate(-99%, -50%);'}
|
|
228
|
-
${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(-99%);'}
|
|
174
|
+
transform: translateY(-50%);
|
|
229
175
|
}
|
|
230
176
|
`}
|
|
231
177
|
`,
|
|
232
178
|
};
|
|
233
|
-
const TooltipWrapper = styled_components_1.default.div
|
|
234
|
-
|
|
179
|
+
const TooltipWrapper = styled_components_1.default.div.attrs(({ anchorName }) => ({
|
|
180
|
+
style: {
|
|
181
|
+
anchorName: anchorName,
|
|
182
|
+
},
|
|
183
|
+
})) `
|
|
235
184
|
display: flex;
|
|
236
185
|
`;
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
186
|
+
const TooltipBody = styled_components_1.default.span.attrs(({ anchorName }) => ({
|
|
187
|
+
style: {
|
|
188
|
+
positionAnchor: anchorName,
|
|
189
|
+
},
|
|
190
|
+
})) `
|
|
191
|
+
position: fixed;
|
|
192
|
+
min-width: 64px;
|
|
241
193
|
padding: var(--tooltip-padding);
|
|
242
|
-
max-width:
|
|
194
|
+
max-width: var(--tooltip-max-width);
|
|
243
195
|
white-space: normal;
|
|
244
196
|
word-break: normal;
|
|
245
197
|
overflow-wrap: break-word;
|
|
198
|
+
text-align: left;
|
|
246
199
|
|
|
247
200
|
border-radius: var(--border-radius-md);
|
|
248
201
|
transition: opacity 0.3s ease-out;
|
|
@@ -270,10 +223,10 @@ const TooltipBody = styled_components_1.default.span `
|
|
|
270
223
|
0px 8px 24px 8px #0000000a,
|
|
271
224
|
0px 4px 12px 0px #00000014;
|
|
272
225
|
|
|
273
|
-
width: ${({ width }) => width || '
|
|
226
|
+
width: ${({ width }) => width || 'max-content'};
|
|
227
|
+
|
|
274
228
|
${({ placement }) => (0, styled_components_1.css) `
|
|
275
229
|
${PLACEMENTS[placement]};
|
|
276
230
|
`}
|
|
277
231
|
`;
|
|
278
|
-
/* eslint-enable theme/no-raw-colors-in-styles */
|
|
279
232
|
//# sourceMappingURL=Tooltip.js.map
|
|
@@ -5,5 +5,9 @@ const styled_components_1 = require("styled-components");
|
|
|
5
5
|
exports.tooltipDarkMode = (0, styled_components_1.css) `
|
|
6
6
|
--tooltip-bg-color: var(--color-warm-grey-4);
|
|
7
7
|
--tooltip-border-color: var(--color-warm-grey-5);
|
|
8
|
+
|
|
9
|
+
.tooltip-copy-button {
|
|
10
|
+
--tooltip-bg-color: var(--color-warm-grey-4);
|
|
11
|
+
}
|
|
8
12
|
`;
|
|
9
13
|
//# sourceMappingURL=variables.dark.js.map
|
|
@@ -20,9 +20,9 @@ exports.tooltip = (0, styled_components_1.css) `
|
|
|
20
20
|
--tooltip-max-width: 400px;
|
|
21
21
|
|
|
22
22
|
.tooltip-copy-button {
|
|
23
|
-
--tooltip-text-color: var(--
|
|
24
|
-
--tooltip-bg-color: var(--
|
|
25
|
-
--tooltip-arrow-color: var(--tooltip-
|
|
23
|
+
--tooltip-text-color: var(--color-static-white);
|
|
24
|
+
--tooltip-bg-color: var(--color-warm-grey-10);
|
|
25
|
+
--tooltip-arrow-color: var(--tooltip-border-color);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
.tooltip-catalog {
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import type { RefObject } from 'react';
|
|
2
|
-
|
|
2
|
+
type OutsideClickRef = RefObject<HTMLElement | null>;
|
|
3
|
+
export declare function useOutsideClick(refs: OutsideClickRef | OutsideClickRef[], handler?: (event: MouseEvent | TouchEvent) => void): void;
|
|
4
|
+
export {};
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useOutsideClick = useOutsideClick;
|
|
4
4
|
const react_1 = require("react");
|
|
5
|
-
function useOutsideClick(
|
|
5
|
+
function useOutsideClick(refs, handler) {
|
|
6
6
|
(0, react_1.useEffect)(() => {
|
|
7
|
+
const refList = Array.isArray(refs) ? refs : [refs];
|
|
7
8
|
const listener = (event) => {
|
|
8
|
-
if (!handler
|
|
9
|
+
if (!handler)
|
|
9
10
|
return;
|
|
11
|
+
const target = event.target;
|
|
12
|
+
const isInside = refList.some((ref) => ref.current && ref.current.contains(target));
|
|
13
|
+
if (!isInside) {
|
|
14
|
+
handler(event);
|
|
10
15
|
}
|
|
11
|
-
handler(event);
|
|
12
16
|
};
|
|
13
17
|
document.addEventListener('mousedown', listener);
|
|
14
18
|
document.addEventListener('touchstart', listener);
|
|
@@ -16,6 +20,6 @@ function useOutsideClick(ref, handler) {
|
|
|
16
20
|
document.removeEventListener('mousedown', listener);
|
|
17
21
|
document.removeEventListener('touchstart', listener);
|
|
18
22
|
};
|
|
19
|
-
}, [
|
|
23
|
+
}, [refs, handler]);
|
|
20
24
|
}
|
|
21
25
|
//# sourceMappingURL=use-outside-click.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.62.0-next.
|
|
3
|
+
"version": "0.62.0-next.7",
|
|
4
4
|
"description": "Shared UI components lib",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"theme",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"lodash.throttle": "^4.1.1",
|
|
32
32
|
"react": "19.2.4",
|
|
33
33
|
"react-dom": "19.2.4",
|
|
34
|
-
"react-router-dom": "^6.
|
|
34
|
+
"react-router-dom": "^6.30.3",
|
|
35
35
|
"styled-components": "^4.1.1 || ^5.3.11 || ^6.0.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@vitest/coverage-v8": "4.0.10",
|
|
52
52
|
"@vitest/ui": "3.2.4",
|
|
53
53
|
"concurrently": "7.6.0",
|
|
54
|
-
"react-router-dom": "^6.
|
|
54
|
+
"react-router-dom": "^6.30.3",
|
|
55
55
|
"resize-observer-polyfill": "1.5.1",
|
|
56
56
|
"rimraf": "5.0.7",
|
|
57
57
|
"styled-components": "5.3.11",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"vitest": "4.0.10",
|
|
64
64
|
"vitest-when": "0.6.2",
|
|
65
65
|
"webpack": "5.94.0",
|
|
66
|
-
"@redocly/realm-asyncapi-sdk": "0.8.0-next.
|
|
66
|
+
"@redocly/realm-asyncapi-sdk": "0.8.0-next.3"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"@tanstack/react-query": "5.62.3",
|
|
@@ -4,7 +4,7 @@ import styled, { css } from 'styled-components';
|
|
|
4
4
|
import type { JSX } from 'react';
|
|
5
5
|
|
|
6
6
|
import { Link } from '@redocly/theme/components/Link/Link';
|
|
7
|
-
import {
|
|
7
|
+
import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
|
|
8
8
|
import { BreadcrumbIcon } from '@redocly/theme/components/Breadcrumbs/BreadcrumbIcon';
|
|
9
9
|
import { trimText } from '@redocly/theme/core/utils';
|
|
10
10
|
import { BREADCRUMB_MAX_LENGTH } from '@redocly/theme/core/constants';
|
|
@@ -48,9 +48,9 @@ export function Breadcrumb({ label, link, isActive, onClick, icon }: BreadcrumbP
|
|
|
48
48
|
);
|
|
49
49
|
|
|
50
50
|
return isTruncated ? (
|
|
51
|
-
<
|
|
51
|
+
<Tooltip tip={label} placement="bottom">
|
|
52
52
|
{breadcrumbContent}
|
|
53
|
-
</
|
|
53
|
+
</Tooltip>
|
|
54
54
|
) : (
|
|
55
55
|
breadcrumbContent
|
|
56
56
|
);
|
|
@@ -8,7 +8,7 @@ import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
|
8
8
|
import { Dropdown } from '@redocly/theme/components/Dropdown/Dropdown';
|
|
9
9
|
import { DropdownMenu } from '@redocly/theme/components/Dropdown/DropdownMenu';
|
|
10
10
|
import { DropdownMenuItem } from '@redocly/theme/components/Dropdown/DropdownMenuItem';
|
|
11
|
-
import {
|
|
11
|
+
import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
|
|
12
12
|
import { GenericIcon } from '@redocly/theme/icons/GenericIcon/GenericIcon';
|
|
13
13
|
import { BREADCRUMB_MAX_LENGTH } from '@redocly/theme/core/constants';
|
|
14
14
|
import { BreadcrumbIcon } from '@redocly/theme/components/Breadcrumbs/BreadcrumbIcon';
|
|
@@ -39,9 +39,9 @@ export function BreadcrumbDropdown({
|
|
|
39
39
|
const isTruncated = label.length > BREADCRUMB_MAX_LENGTH;
|
|
40
40
|
|
|
41
41
|
const triggerContent = isTruncated ? (
|
|
42
|
-
<
|
|
42
|
+
<Tooltip tip={label} placement="bottom">
|
|
43
43
|
<TriggerContentWrapper>{children}</TriggerContentWrapper>
|
|
44
|
-
</
|
|
44
|
+
</Tooltip>
|
|
45
45
|
) : (
|
|
46
46
|
children
|
|
47
47
|
);
|
|
@@ -3,7 +3,7 @@ import styled from 'styled-components';
|
|
|
3
3
|
|
|
4
4
|
import { CATALOG_TAG_MAX_LENGTH } from '@redocly/theme/core/constants';
|
|
5
5
|
import { Tag, TagProps } from '@redocly/theme/components/Tag/Tag';
|
|
6
|
-
import {
|
|
6
|
+
import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
|
|
7
7
|
import { CatalogHighlight } from '@redocly/theme/components/Catalog/CatalogHighlight';
|
|
8
8
|
import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
9
9
|
|
|
@@ -53,7 +53,7 @@ export function CatalogTagsWithTooltip({
|
|
|
53
53
|
const remainingCount = items.length - itemsToShow;
|
|
54
54
|
|
|
55
55
|
return (
|
|
56
|
-
<
|
|
56
|
+
<Tooltip tip={items.join(', ')} placement="bottom" className="catalog" width="400px">
|
|
57
57
|
<CatalogTagsWrapper data-component-name="Catalog/CatalogTagsWithTooltip">
|
|
58
58
|
{displayedItems.map((item, index) => (
|
|
59
59
|
<Tag
|
|
@@ -70,7 +70,7 @@ export function CatalogTagsWithTooltip({
|
|
|
70
70
|
+{remainingCount} {translate('catalog.tags.more', 'more')}
|
|
71
71
|
</MoreTagsButton>
|
|
72
72
|
</CatalogTagsWrapper>
|
|
73
|
-
</
|
|
73
|
+
</Tooltip>
|
|
74
74
|
);
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -6,7 +6,7 @@ import type { CodeBlockItems } from '@redocly/theme/components/CodeBlock/CodeBlo
|
|
|
6
6
|
|
|
7
7
|
import { CodeBlockTabs } from '@redocly/theme/components/CodeBlock/CodeBlockTabs';
|
|
8
8
|
import { CopyButton } from '@redocly/theme/components/Buttons/CopyButton';
|
|
9
|
-
import {
|
|
9
|
+
import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
|
|
10
10
|
import { useThemeHooks, useThemeConfig } from '@redocly/theme/core/hooks';
|
|
11
11
|
import { DeselectIcon } from '@redocly/theme/icons/DeselectIcon/DeselectIcon';
|
|
12
12
|
import { MaximizeIcon } from '@redocly/theme/icons/MaximizeIcon/MaximizeIcon';
|
|
@@ -86,9 +86,10 @@ export function CodeBlockControls({
|
|
|
86
86
|
<ControlsWrapper>
|
|
87
87
|
{dropdown && <CodeBlockDropdown {...dropdown} />}
|
|
88
88
|
{report && !report.hidden && !report?.props?.hide ? (
|
|
89
|
-
<
|
|
89
|
+
<Tooltip
|
|
90
90
|
tip={translate('codeSnippet.report.tooltipText', 'Report a problem')}
|
|
91
91
|
placement="top"
|
|
92
|
+
arrowPosition="right"
|
|
92
93
|
>
|
|
93
94
|
<ControlButton
|
|
94
95
|
variant="text"
|
|
@@ -99,13 +100,14 @@ export function CodeBlockControls({
|
|
|
99
100
|
>
|
|
100
101
|
{controlsType != 'icon' && (report.props?.buttonText || 'Report')}
|
|
101
102
|
</ControlButton>
|
|
102
|
-
</
|
|
103
|
+
</Tooltip>
|
|
103
104
|
) : null}
|
|
104
105
|
|
|
105
106
|
{expand && !codeSnippet?.expand?.hide ? (
|
|
106
|
-
<
|
|
107
|
+
<Tooltip
|
|
107
108
|
tip={translate('codeSnippet.expand.tooltipText', 'Expand all')}
|
|
108
109
|
placement="top"
|
|
110
|
+
arrowPosition="right"
|
|
109
111
|
>
|
|
110
112
|
<ControlButton
|
|
111
113
|
variant="text"
|
|
@@ -116,13 +118,14 @@ export function CodeBlockControls({
|
|
|
116
118
|
>
|
|
117
119
|
{controlsType !== 'icon' && (expand?.label || 'Expand all')}
|
|
118
120
|
</ControlButton>
|
|
119
|
-
</
|
|
121
|
+
</Tooltip>
|
|
120
122
|
) : null}
|
|
121
123
|
|
|
122
124
|
{collapse && !codeSnippet?.collapse?.hide ? (
|
|
123
|
-
<
|
|
125
|
+
<Tooltip
|
|
124
126
|
tip={translate('codeSnippet.collapse.tooltipText', 'Collapse all')}
|
|
125
127
|
placement="top"
|
|
128
|
+
arrowPosition="right"
|
|
126
129
|
>
|
|
127
130
|
<ControlButton
|
|
128
131
|
variant="text"
|
|
@@ -133,7 +136,7 @@ export function CodeBlockControls({
|
|
|
133
136
|
>
|
|
134
137
|
{controlsType !== 'icon' && (expand?.label || 'Collapse all')}
|
|
135
138
|
</ControlButton>
|
|
136
|
-
</
|
|
139
|
+
</Tooltip>
|
|
137
140
|
) : null}
|
|
138
141
|
|
|
139
142
|
{select ? (
|
|
@@ -161,9 +164,10 @@ export function CodeBlockControls({
|
|
|
161
164
|
) : null}
|
|
162
165
|
|
|
163
166
|
{copy && !codeSnippet?.copy?.hide ? (
|
|
164
|
-
<
|
|
167
|
+
<Tooltip
|
|
165
168
|
tip={translate('codeSnippet.copy.tooltipText', 'Copy to clipboard')}
|
|
166
169
|
placement="top"
|
|
170
|
+
arrowPosition="right"
|
|
167
171
|
>
|
|
168
172
|
<StyledCopyButton
|
|
169
173
|
data={copy.data}
|
|
@@ -184,7 +188,7 @@ export function CodeBlockControls({
|
|
|
184
188
|
}
|
|
185
189
|
}}
|
|
186
190
|
/>
|
|
187
|
-
</
|
|
191
|
+
</Tooltip>
|
|
188
192
|
) : null}
|
|
189
193
|
</ControlsWrapper>
|
|
190
194
|
</>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { memo, useEffect, useRef, useId } from 'react';
|
|
2
2
|
import styled, { css } from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import type { JSX, PropsWithChildren, ReactNode } from 'react';
|
|
@@ -15,10 +15,10 @@ export type TooltipProps = {
|
|
|
15
15
|
width?: string;
|
|
16
16
|
dataTestId?: string;
|
|
17
17
|
disabled?: boolean;
|
|
18
|
-
arrowPosition?: '
|
|
18
|
+
arrowPosition?: 'left' | 'right' | 'center';
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
function TooltipComponent({
|
|
22
22
|
children,
|
|
23
23
|
isOpen,
|
|
24
24
|
tip,
|
|
@@ -30,111 +30,55 @@ export function TooltipComponent({
|
|
|
30
30
|
disabled = false,
|
|
31
31
|
arrowPosition = 'center',
|
|
32
32
|
}: PropsWithChildren<TooltipProps>): JSX.Element {
|
|
33
|
-
const
|
|
33
|
+
const tooltipWrapperRef = useRef<HTMLDivElement | null>(null);
|
|
34
|
+
const tooltipBodyRef = useRef<HTMLDivElement | null>(null);
|
|
34
35
|
const { isOpened, handleOpen, handleClose } = useControl(isOpen);
|
|
35
|
-
const
|
|
36
|
+
const anchorName = `--tooltip${useId().replace(/:/g, '')}`;
|
|
36
37
|
|
|
37
|
-
useOutsideClick(
|
|
38
|
+
useOutsideClick(isOpened ? [tooltipWrapperRef, tooltipBodyRef] : tooltipWrapperRef, handleClose);
|
|
38
39
|
|
|
39
40
|
const isControlled = isOpen !== undefined;
|
|
40
41
|
|
|
41
|
-
const updateTooltipPosition = useCallback(() => {
|
|
42
|
-
if (isOpened && ref.current) {
|
|
43
|
-
const rect = ref.current.getBoundingClientRect();
|
|
44
|
-
|
|
45
|
-
let top = 0;
|
|
46
|
-
let left = 0;
|
|
47
|
-
|
|
48
|
-
switch (placement) {
|
|
49
|
-
case 'top':
|
|
50
|
-
top = rect.top;
|
|
51
|
-
if (arrowPosition === 'left') {
|
|
52
|
-
left = rect.left - 24;
|
|
53
|
-
} else if (arrowPosition === 'right') {
|
|
54
|
-
left = rect.right + 24;
|
|
55
|
-
} else {
|
|
56
|
-
left = rect.left + rect.width / 2;
|
|
57
|
-
}
|
|
58
|
-
break;
|
|
59
|
-
case 'bottom':
|
|
60
|
-
top = rect.bottom;
|
|
61
|
-
if (arrowPosition === 'left') {
|
|
62
|
-
left = rect.left - 24;
|
|
63
|
-
} else if (arrowPosition === 'right') {
|
|
64
|
-
left = rect.right + 24;
|
|
65
|
-
} else {
|
|
66
|
-
left = rect.left + rect.width / 2;
|
|
67
|
-
}
|
|
68
|
-
break;
|
|
69
|
-
case 'left':
|
|
70
|
-
top = rect.top + rect.height / 2;
|
|
71
|
-
left = rect.left;
|
|
72
|
-
break;
|
|
73
|
-
case 'right':
|
|
74
|
-
top = rect.top + rect.height / 2;
|
|
75
|
-
left = rect.right;
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
setTooltipPosition({ top, left });
|
|
80
|
-
}
|
|
81
|
-
}, [isOpened, placement, arrowPosition]);
|
|
82
|
-
|
|
83
42
|
useEffect(() => {
|
|
84
|
-
if (
|
|
85
|
-
updateTooltipPosition();
|
|
86
|
-
|
|
87
|
-
const handleScroll = () => updateTooltipPosition();
|
|
88
|
-
const handleResize = () => updateTooltipPosition();
|
|
89
|
-
|
|
90
|
-
window.addEventListener('scroll', handleScroll, true);
|
|
91
|
-
window.addEventListener('resize', handleResize);
|
|
92
|
-
|
|
93
|
-
return () => {
|
|
94
|
-
window.removeEventListener('scroll', handleScroll, true);
|
|
95
|
-
window.removeEventListener('resize', handleResize);
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
}, [isOpened, placement, updateTooltipPosition]);
|
|
43
|
+
if (!isControlled) return;
|
|
99
44
|
|
|
100
|
-
useEffect(() => {
|
|
101
45
|
if (isOpen && !disabled) {
|
|
102
46
|
handleOpen();
|
|
103
47
|
} else {
|
|
104
48
|
handleClose();
|
|
105
49
|
}
|
|
106
|
-
}, [isOpen, handleOpen, handleClose
|
|
107
|
-
|
|
108
|
-
const controllers =
|
|
109
|
-
!
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
50
|
+
}, [isOpen, disabled, isControlled, handleOpen, handleClose]);
|
|
51
|
+
|
|
52
|
+
const controllers =
|
|
53
|
+
!isControlled && !disabled
|
|
54
|
+
? {
|
|
55
|
+
onMouseEnter: handleOpen,
|
|
56
|
+
onMouseLeave: handleClose,
|
|
57
|
+
onClick: handleClose,
|
|
58
|
+
onFocus: handleOpen,
|
|
59
|
+
onBlur: handleClose,
|
|
60
|
+
}
|
|
61
|
+
: {};
|
|
116
62
|
|
|
117
63
|
return (
|
|
118
64
|
<TooltipWrapper
|
|
119
|
-
ref={
|
|
65
|
+
ref={tooltipWrapperRef}
|
|
120
66
|
{...controllers}
|
|
121
67
|
className={`tooltip-${className}`}
|
|
122
68
|
data-component-name="Tooltip/Tooltip"
|
|
69
|
+
anchorName={anchorName}
|
|
123
70
|
>
|
|
124
71
|
{children}
|
|
125
72
|
{isOpened && !disabled && (
|
|
126
73
|
<Portal>
|
|
127
74
|
<TooltipBody
|
|
75
|
+
ref={tooltipBodyRef}
|
|
128
76
|
data-testid={dataTestId || (typeof tip === 'string' ? tip : '')}
|
|
129
77
|
placement={placement}
|
|
130
78
|
width={width}
|
|
131
79
|
withArrow={withArrow}
|
|
132
80
|
arrowPosition={arrowPosition}
|
|
133
|
-
|
|
134
|
-
position: 'fixed',
|
|
135
|
-
top: tooltipPosition.top,
|
|
136
|
-
left: tooltipPosition.left,
|
|
137
|
-
}}
|
|
81
|
+
anchorName={anchorName}
|
|
138
82
|
>
|
|
139
83
|
{tip}
|
|
140
84
|
</TooltipBody>
|
|
@@ -148,20 +92,21 @@ export const Tooltip = memo<PropsWithChildren<TooltipProps>>(TooltipComponent);
|
|
|
148
92
|
|
|
149
93
|
const PLACEMENTS = {
|
|
150
94
|
top: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
|
|
95
|
+
bottom: anchor(top);
|
|
151
96
|
${({ withArrow, arrowPosition }) =>
|
|
152
97
|
withArrow && arrowPosition === 'left'
|
|
153
98
|
? css`
|
|
154
|
-
transform: translate(
|
|
155
|
-
|
|
99
|
+
transform: translate(-32px, -6px);
|
|
100
|
+
left: anchor(center);
|
|
156
101
|
`
|
|
157
102
|
: arrowPosition === 'right'
|
|
158
103
|
? css`
|
|
159
|
-
transform: translate(
|
|
160
|
-
|
|
104
|
+
transform: translate(32px, -6px);
|
|
105
|
+
right: anchor(center);
|
|
161
106
|
`
|
|
162
107
|
: css`
|
|
163
|
-
transform: translate(-50%, -
|
|
164
|
-
|
|
108
|
+
transform: translate(-50%, -6px);
|
|
109
|
+
left: anchor(center);
|
|
165
110
|
`}
|
|
166
111
|
|
|
167
112
|
${({ withArrow, arrowPosition }) =>
|
|
@@ -174,27 +119,28 @@ const PLACEMENTS = {
|
|
|
174
119
|
border-top-style: solid;
|
|
175
120
|
border-radius: 2px;
|
|
176
121
|
bottom: 0;
|
|
177
|
-
${arrowPosition === 'left' && 'left: 16px; transform: translateY(
|
|
178
|
-
${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%,
|
|
179
|
-
${arrowPosition === 'right' && 'right: 16px; transform: translateY(
|
|
122
|
+
${arrowPosition === 'left' && 'left: 16px; transform: translateY(100%);'}
|
|
123
|
+
${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 100%);'}
|
|
124
|
+
${arrowPosition === 'right' && 'right: 16px; transform: translateY(100%);'}
|
|
180
125
|
}
|
|
181
126
|
`}
|
|
182
127
|
`,
|
|
183
128
|
bottom: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
|
|
129
|
+
top: anchor(bottom);
|
|
184
130
|
${({ withArrow, arrowPosition }) =>
|
|
185
131
|
withArrow && arrowPosition === 'left'
|
|
186
132
|
? css`
|
|
187
|
-
transform: translate(
|
|
188
|
-
|
|
133
|
+
transform: translate(-32px, 6px);
|
|
134
|
+
left: anchor(center);
|
|
189
135
|
`
|
|
190
136
|
: arrowPosition === 'right'
|
|
191
137
|
? css`
|
|
192
|
-
transform: translate(
|
|
193
|
-
|
|
138
|
+
transform: translate(32px, 6px);
|
|
139
|
+
right: anchor(center);
|
|
194
140
|
`
|
|
195
141
|
: css`
|
|
196
|
-
transform: translate(-50%,
|
|
197
|
-
|
|
142
|
+
transform: translate(-50%, 6px);
|
|
143
|
+
left: anchor(center);
|
|
198
144
|
`}
|
|
199
145
|
|
|
200
146
|
${({ withArrow, arrowPosition }) =>
|
|
@@ -207,17 +153,19 @@ const PLACEMENTS = {
|
|
|
207
153
|
border-bottom-style: solid;
|
|
208
154
|
border-radius: 0 0 2px 2px;
|
|
209
155
|
top: 0;
|
|
210
|
-
${arrowPosition === 'left' && 'left: 16px; transform: translateY(-
|
|
211
|
-
${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -
|
|
212
|
-
${arrowPosition === 'right' && 'right: 16px; transform: translateY(-
|
|
156
|
+
${arrowPosition === 'left' && 'left: 16px; transform: translateY(-100%);'}
|
|
157
|
+
${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -100%);'}
|
|
158
|
+
${arrowPosition === 'right' && 'right: 16px; transform: translateY(-100%);'}
|
|
213
159
|
}
|
|
214
160
|
`}
|
|
215
161
|
`,
|
|
216
162
|
left: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
|
|
217
163
|
transform: translate(-100%, -50%);
|
|
218
|
-
margin-left: -
|
|
164
|
+
margin-left: -7px;
|
|
165
|
+
top: anchor(center);
|
|
166
|
+
left: anchor(left);
|
|
219
167
|
|
|
220
|
-
${({ withArrow
|
|
168
|
+
${({ withArrow }) =>
|
|
221
169
|
withArrow &&
|
|
222
170
|
css`
|
|
223
171
|
&::after {
|
|
@@ -226,19 +174,19 @@ const PLACEMENTS = {
|
|
|
226
174
|
border-left-width: 8px;
|
|
227
175
|
border-left-style: solid;
|
|
228
176
|
border-radius: 2px 0 0 2px;
|
|
177
|
+
right: -9px;
|
|
229
178
|
top: 50%;
|
|
230
|
-
|
|
231
|
-
${arrowPosition === 'top' && 'top: 16px; transform: translateX(99%);'}
|
|
232
|
-
${arrowPosition === 'center' && 'top: 50%; transform: translate(99%, -50%);'}
|
|
233
|
-
${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(99%);'}
|
|
179
|
+
transform: translateY(-50%);
|
|
234
180
|
}
|
|
235
181
|
`}
|
|
236
182
|
`,
|
|
237
183
|
right: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
|
|
238
184
|
transform: translate(0, -50%);
|
|
239
|
-
margin-left:
|
|
185
|
+
margin-left: 7px;
|
|
186
|
+
top: anchor(center);
|
|
187
|
+
left: anchor(right);
|
|
240
188
|
|
|
241
|
-
${({ withArrow
|
|
189
|
+
${({ withArrow }) =>
|
|
242
190
|
withArrow &&
|
|
243
191
|
css`
|
|
244
192
|
&::after {
|
|
@@ -247,31 +195,40 @@ const PLACEMENTS = {
|
|
|
247
195
|
border-right-width: 8px;
|
|
248
196
|
border-right-style: solid;
|
|
249
197
|
border-radius: 0 2px 2px 0;
|
|
198
|
+
left: -9px;
|
|
250
199
|
top: 50%;
|
|
251
|
-
|
|
252
|
-
${arrowPosition === 'top' && 'top: 16px; transform: translateX(-99%);'}
|
|
253
|
-
${arrowPosition === 'center' && 'top: 50%; transform: translate(-99%, -50%);'}
|
|
254
|
-
${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(-99%);'}
|
|
200
|
+
transform: translateY(-50%);
|
|
255
201
|
}
|
|
256
202
|
`}
|
|
257
203
|
`,
|
|
258
204
|
};
|
|
259
205
|
|
|
260
|
-
const TooltipWrapper = styled.div
|
|
261
|
-
|
|
206
|
+
const TooltipWrapper = styled.div.attrs<{ anchorName: string }>(({ anchorName }) => ({
|
|
207
|
+
style: {
|
|
208
|
+
anchorName: anchorName,
|
|
209
|
+
} as React.CSSProperties,
|
|
210
|
+
}))<{ anchorName: string }>`
|
|
262
211
|
display: flex;
|
|
263
212
|
`;
|
|
264
|
-
/* eslint-disable theme/no-raw-colors-in-styles */
|
|
265
|
-
const TooltipBody = styled.span<
|
|
266
|
-
Pick<Required<TooltipProps>, 'placement' | 'withArrow' | 'arrowPosition'> & { width?: string }
|
|
267
|
-
>`
|
|
268
|
-
display: inline-block;
|
|
269
213
|
|
|
214
|
+
const TooltipBody = styled.span.attrs<{ anchorName: string }>(({ anchorName }) => ({
|
|
215
|
+
style: {
|
|
216
|
+
positionAnchor: anchorName,
|
|
217
|
+
} as React.CSSProperties,
|
|
218
|
+
}))<
|
|
219
|
+
Pick<Required<TooltipProps>, 'placement' | 'withArrow' | 'arrowPosition'> & {
|
|
220
|
+
width?: string;
|
|
221
|
+
anchorName: string;
|
|
222
|
+
}
|
|
223
|
+
>`
|
|
224
|
+
position: fixed;
|
|
225
|
+
min-width: 64px;
|
|
270
226
|
padding: var(--tooltip-padding);
|
|
271
|
-
max-width:
|
|
227
|
+
max-width: var(--tooltip-max-width);
|
|
272
228
|
white-space: normal;
|
|
273
229
|
word-break: normal;
|
|
274
230
|
overflow-wrap: break-word;
|
|
231
|
+
text-align: left;
|
|
275
232
|
|
|
276
233
|
border-radius: var(--border-radius-md);
|
|
277
234
|
transition: opacity 0.3s ease-out;
|
|
@@ -299,9 +256,9 @@ const TooltipBody = styled.span<
|
|
|
299
256
|
0px 8px 24px 8px #0000000a,
|
|
300
257
|
0px 4px 12px 0px #00000014;
|
|
301
258
|
|
|
302
|
-
width: ${({ width }) => width || '
|
|
259
|
+
width: ${({ width }) => width || 'max-content'};
|
|
260
|
+
|
|
303
261
|
${({ placement }) => css`
|
|
304
262
|
${PLACEMENTS[placement]};
|
|
305
263
|
`}
|
|
306
264
|
`;
|
|
307
|
-
/* eslint-enable theme/no-raw-colors-in-styles */
|
|
@@ -18,9 +18,9 @@ export const tooltip = css`
|
|
|
18
18
|
--tooltip-max-width: 400px;
|
|
19
19
|
|
|
20
20
|
.tooltip-copy-button {
|
|
21
|
-
--tooltip-text-color: var(--
|
|
22
|
-
--tooltip-bg-color: var(--
|
|
23
|
-
--tooltip-arrow-color: var(--tooltip-
|
|
21
|
+
--tooltip-text-color: var(--color-static-white);
|
|
22
|
+
--tooltip-bg-color: var(--color-warm-grey-10);
|
|
23
|
+
--tooltip-arrow-color: var(--tooltip-border-color);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
.tooltip-catalog {
|
|
@@ -2,22 +2,33 @@ import { useEffect } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import type { RefObject } from 'react';
|
|
4
4
|
|
|
5
|
+
type OutsideClickRef = RefObject<HTMLElement | null>;
|
|
6
|
+
|
|
5
7
|
export function useOutsideClick(
|
|
6
|
-
|
|
8
|
+
refs: OutsideClickRef | OutsideClickRef[],
|
|
7
9
|
handler?: (event: MouseEvent | TouchEvent) => void,
|
|
8
10
|
): void {
|
|
9
11
|
useEffect(() => {
|
|
12
|
+
const refList = Array.isArray(refs) ? refs : [refs];
|
|
13
|
+
|
|
10
14
|
const listener = (event: MouseEvent | TouchEvent) => {
|
|
11
|
-
if (!handler
|
|
12
|
-
|
|
15
|
+
if (!handler) return;
|
|
16
|
+
|
|
17
|
+
const target = event.target as Node;
|
|
18
|
+
|
|
19
|
+
const isInside = refList.some((ref) => ref.current && ref.current.contains(target));
|
|
20
|
+
|
|
21
|
+
if (!isInside) {
|
|
22
|
+
handler(event);
|
|
13
23
|
}
|
|
14
|
-
handler(event);
|
|
15
24
|
};
|
|
25
|
+
|
|
16
26
|
document.addEventListener('mousedown', listener);
|
|
17
27
|
document.addEventListener('touchstart', listener);
|
|
28
|
+
|
|
18
29
|
return () => {
|
|
19
30
|
document.removeEventListener('mousedown', listener);
|
|
20
31
|
document.removeEventListener('touchstart', listener);
|
|
21
32
|
};
|
|
22
|
-
}, [
|
|
33
|
+
}, [refs, handler]);
|
|
23
34
|
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { JSX, ReactElement } from 'react';
|
|
2
|
-
import type { TooltipProps } from '../../components/Tooltip/Tooltip';
|
|
3
|
-
export type TooltipWrapperProps = {
|
|
4
|
-
children: ReactElement;
|
|
5
|
-
tip: string;
|
|
6
|
-
placement?: TooltipProps['placement'];
|
|
7
|
-
width?: string;
|
|
8
|
-
className?: string;
|
|
9
|
-
showOnHover?: boolean;
|
|
10
|
-
disabled?: boolean;
|
|
11
|
-
};
|
|
12
|
-
export declare function TooltipWrapper({ children, tip, placement, width, className, showOnHover, disabled, }: TooltipWrapperProps): JSX.Element;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.TooltipWrapper = TooltipWrapper;
|
|
7
|
-
const styled_components_1 = __importDefault(require("styled-components"));
|
|
8
|
-
const react_1 = __importDefault(require("react"));
|
|
9
|
-
const hooks_1 = require("../../core/hooks");
|
|
10
|
-
const Tooltip_1 = require("../../components/Tooltip/Tooltip");
|
|
11
|
-
function TooltipWrapper({ children, tip, placement = 'top', width = 'max-content', className = '', showOnHover = true, disabled = false, }) {
|
|
12
|
-
const tooltip = (0, hooks_1.useControl)(false);
|
|
13
|
-
const handleMouseEnter = () => {
|
|
14
|
-
if (showOnHover && !disabled) {
|
|
15
|
-
tooltip.handleOpen();
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
const handleMouseLeave = () => {
|
|
19
|
-
if (showOnHover) {
|
|
20
|
-
tooltip.handleClose();
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
const handleClick = () => {
|
|
24
|
-
if (showOnHover) {
|
|
25
|
-
tooltip.handleClose();
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
return (react_1.default.createElement(Tooltip_1.Tooltip, { className: className, tip: tip, isOpen: tooltip.isOpened, placement: placement, width: width },
|
|
29
|
-
react_1.default.createElement(TooltipEventWrapper, { onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onClick: handleClick }, children)));
|
|
30
|
-
}
|
|
31
|
-
const TooltipEventWrapper = styled_components_1.default.div `
|
|
32
|
-
display: contents;
|
|
33
|
-
`;
|
|
34
|
-
//# sourceMappingURL=TooltipWrapper.js.map
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import styled from 'styled-components';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
4
|
-
import type { JSX, ReactElement } from 'react';
|
|
5
|
-
import type { TooltipProps } from '@redocly/theme/components/Tooltip/Tooltip';
|
|
6
|
-
|
|
7
|
-
import { useControl } from '@redocly/theme/core/hooks';
|
|
8
|
-
import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
|
|
9
|
-
|
|
10
|
-
export type TooltipWrapperProps = {
|
|
11
|
-
children: ReactElement;
|
|
12
|
-
tip: string;
|
|
13
|
-
placement?: TooltipProps['placement'];
|
|
14
|
-
width?: string;
|
|
15
|
-
className?: string;
|
|
16
|
-
showOnHover?: boolean;
|
|
17
|
-
disabled?: boolean;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export function TooltipWrapper({
|
|
21
|
-
children,
|
|
22
|
-
tip,
|
|
23
|
-
placement = 'top',
|
|
24
|
-
width = 'max-content',
|
|
25
|
-
className = '',
|
|
26
|
-
showOnHover = true,
|
|
27
|
-
disabled = false,
|
|
28
|
-
}: TooltipWrapperProps): JSX.Element {
|
|
29
|
-
const tooltip = useControl(false);
|
|
30
|
-
|
|
31
|
-
const handleMouseEnter = (): void => {
|
|
32
|
-
if (showOnHover && !disabled) {
|
|
33
|
-
tooltip.handleOpen();
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const handleMouseLeave = (): void => {
|
|
38
|
-
if (showOnHover) {
|
|
39
|
-
tooltip.handleClose();
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const handleClick = (): void => {
|
|
44
|
-
if (showOnHover) {
|
|
45
|
-
tooltip.handleClose();
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<Tooltip
|
|
51
|
-
className={className}
|
|
52
|
-
tip={tip}
|
|
53
|
-
isOpen={tooltip.isOpened}
|
|
54
|
-
placement={placement}
|
|
55
|
-
width={width}
|
|
56
|
-
>
|
|
57
|
-
<TooltipEventWrapper
|
|
58
|
-
onMouseEnter={handleMouseEnter}
|
|
59
|
-
onMouseLeave={handleMouseLeave}
|
|
60
|
-
onClick={handleClick}
|
|
61
|
-
>
|
|
62
|
-
{children}
|
|
63
|
-
</TooltipEventWrapper>
|
|
64
|
-
</Tooltip>
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const TooltipEventWrapper = styled.div`
|
|
69
|
-
display: contents;
|
|
70
|
-
`;
|