mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
Feat tooltip wrapper (#3732)
* feat: TooltipWrapper 的component组件完善 * feat: TooltipWrapper 文字提示容器 render组件 & 文档完善 * feat: TooltipWrapper 文字提示容器render组件兼容tooltip属性 * fix: 修复 tooltip组件 PR中相关问题 * fix: TooltipWrapper 属性children调整 & 标题内容支持DOM解析 Co-authored-by: ”jiatianqi“ <”jiatianqi@baidu.com“>
This commit is contained in:
parent
9a19956b0f
commit
7f8a93716f
@ -26,14 +26,14 @@ order: 59
|
||||
"items": [
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "提示文字",
|
||||
"content": "提示文字",
|
||||
"body": "hover 激活文字提示",
|
||||
"className": "mb-1"
|
||||
},
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"title": "标题",
|
||||
"tooltip": "提示文字",
|
||||
"content": "提示文字",
|
||||
"trigger": "click",
|
||||
"body": "click 激活文字提示",
|
||||
"className": "mb-1"
|
||||
@ -49,7 +49,7 @@ order: 59
|
||||
[
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "删除提示",
|
||||
"content": "删除提示",
|
||||
"inline": true,
|
||||
"body": [
|
||||
{
|
||||
@ -89,7 +89,7 @@ order: 59
|
||||
"items": [
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "提示文字",
|
||||
"content": "提示文字",
|
||||
"body": [
|
||||
{
|
||||
"type": "icon",
|
||||
@ -116,7 +116,7 @@ order: 59
|
||||
"items": [
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "提示文字",
|
||||
"content": "提示文字",
|
||||
"placement": "left",
|
||||
"body": [
|
||||
{
|
||||
@ -132,7 +132,7 @@ order: 59
|
||||
},
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "提示文字",
|
||||
"content": "提示文字",
|
||||
"placement": "right",
|
||||
"body": [
|
||||
{
|
||||
@ -160,7 +160,7 @@ order: 59
|
||||
"items": [
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "提示文字",
|
||||
"content": "提示文字",
|
||||
"placement": "bottom",
|
||||
"body": [
|
||||
{
|
||||
@ -180,6 +180,54 @@ order: 59
|
||||
}
|
||||
```
|
||||
|
||||
## 位置偏移
|
||||
|
||||
组件提供了关于相对提示位置的垂直、水平位置上的偏移,默认[0, 0]。
|
||||
|
||||
```schema: scope="body"
|
||||
[
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"title": "标题",
|
||||
"content": "文案提示位置偏移 [10, -20]",
|
||||
"offset": [10, -20],
|
||||
"inline": true,
|
||||
"className": "mr-2",
|
||||
"body": [
|
||||
{
|
||||
"type": "tpl",
|
||||
"tpl": "向右偏移10px向上偏移20px"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
## 展示箭头
|
||||
|
||||
`showArrow` 为 `false` 不展示箭头。
|
||||
|
||||
```schema: scope="body"
|
||||
[
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"title": "标题",
|
||||
"content": "提示内容",
|
||||
"showArrow": false,
|
||||
"inline": true,
|
||||
"className": "mr-2",
|
||||
"body": [
|
||||
{
|
||||
"type": "tpl",
|
||||
"tpl": "没有箭头"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
## 主题色
|
||||
|
||||
组件提供了两个不同的主题:`dark` 和 `light`,默认使用`light`。
|
||||
@ -189,7 +237,7 @@ order: 59
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"title": "标题",
|
||||
"tooltip": "文案提示",
|
||||
"content": "文案提示",
|
||||
"inline": true,
|
||||
"className": "mr-2",
|
||||
"body": [
|
||||
@ -202,7 +250,7 @@ order: 59
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"title": "标题",
|
||||
"tooltip": "文案提示",
|
||||
"content": "文案提示",
|
||||
"inline": true,
|
||||
"tooltipTheme": "dark",
|
||||
"body": [
|
||||
@ -216,9 +264,34 @@ order: 59
|
||||
|
||||
```
|
||||
|
||||
## 延迟打开&关闭
|
||||
|
||||
`mouseEnterDelay` 为延迟展示, `mouseLeaveDelay` 为延迟隐藏,
|
||||
|
||||
```schema: scope="body"
|
||||
[
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"title": "标题",
|
||||
"content": "提示内容",
|
||||
"mouseEnterDelay": 1000,
|
||||
"mouseLeaveDelay": 2000,
|
||||
"inline": true,
|
||||
"className": "mr-2",
|
||||
"body": [
|
||||
{
|
||||
"type": "tpl",
|
||||
"tpl": "延迟1s展示,延迟2s隐藏"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
## 动态文案
|
||||
|
||||
`tooltip` 和 `title` 支持变量映射,可以从上下文中动态获取提示文案。
|
||||
`content` 和 `title` 支持变量映射,可以从上下文中动态获取提示文案。
|
||||
|
||||
```schema
|
||||
{
|
||||
@ -228,7 +301,7 @@ order: 59
|
||||
},
|
||||
body: {
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "${text}",
|
||||
"content": "${text}",
|
||||
"body": {
|
||||
"type": "html",
|
||||
"style": {
|
||||
@ -252,21 +325,21 @@ order: 59
|
||||
[
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "文字提示",
|
||||
"content": "文字提示",
|
||||
"inline": true,
|
||||
"className": "p-1 mr-3 border-2 border-solid border-indigo-400",
|
||||
"body": "内联容器1"
|
||||
},
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "文字提示",
|
||||
"content": "文字提示",
|
||||
"inline": true,
|
||||
"className": "p-1 mr-3 border-2 border-solid border-indigo-400",
|
||||
"body": "内联容器2"
|
||||
},
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "文字提示",
|
||||
"content": "文字提示",
|
||||
"className": "p-1 mt-3 border-2 border-solid border-green-400",
|
||||
"body": "非内联容器"
|
||||
}
|
||||
@ -281,7 +354,7 @@ order: 59
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "文字提示(加粗)",
|
||||
"content": "文字提示(加粗)",
|
||||
"inline": true,
|
||||
"style": {
|
||||
fontStyle: "italic"
|
||||
@ -305,7 +378,7 @@ order: 59
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "tooltip-wrapper",
|
||||
"tooltip": "文字提示",
|
||||
"content": "文字提示",
|
||||
"wrapperComponent": "pre",
|
||||
"body": "function HelloWorld() {\n console.log('Hello World');\n}"
|
||||
}
|
||||
@ -317,10 +390,15 @@ order: 59
|
||||
| ---------------- | ----------------------------------------------------------------------- | ------------------- | ---------------------------------------------- |
|
||||
| type | `string` | `"tooltip-wrapper"` | 指定为文字提示容器组件 |
|
||||
| title | `string` | `""` | 文字提示标题 |
|
||||
| tooltip | `string` | `""` | 文字提示 |
|
||||
| content | `string` | `""` | 文字提示内容, 兼容之前的 tooltip 属性 |
|
||||
| placement | `"top" \| "left" \| "right" \| "bottom" ` | `"top"` | 文字提示浮层出现位置 |
|
||||
| tooltipTheme | `"light" \| "dark"` | `"light"` | 主题样式, 默认为 light |
|
||||
| offset | `[number, number]` | `[0, 0]` | 文字提示浮层位置相对偏移量,单位 px |
|
||||
| showArrow | `boolean` | `true` | 是否展示浮层指向箭头 |
|
||||
| disabled | `boolean` | `false` | 是否禁用浮层提示 |
|
||||
| trigger | `"hover" \| "click" \| "focus" \| Array<"hover" \| "click" \| "focus">` | `"hover"` | 浮层触发方式,支持数组写法`["hover", "click"]` |
|
||||
| delay | `number` | `0` | 浮层隐藏延迟时间,单位 ms |
|
||||
| mouseEnterDelay | `number` | `0` | 浮层延迟展示时间,单位 ms |
|
||||
| mouseLeaveDelay | `number` | `300` | 浮层延迟隐藏时间,单位 ms |
|
||||
| rootClose | `boolean` | `true` | 是否点击非内容区域关闭提示 |
|
||||
| inline | `boolean` | `false` | 内容区是否内联显示 |
|
||||
| wrapperComponent | `string` | `"div" \| "span"` | 容器标签名 |
|
||||
|
@ -59,6 +59,8 @@
|
||||
|
||||
--boxShadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--boxShadowSm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--boxTooltipShadow: 0 4px 6px 1px rgb(8 14 26 / 6%),
|
||||
0 1px 10px 0 rgb(8 14 26 / 5%), 0 2px 4px -1px rgb(8 14 26 / 4%);
|
||||
|
||||
--lineHeightBase: 1.5;
|
||||
|
||||
@ -1453,14 +1455,15 @@
|
||||
--Tooltip-bg--dark: rgba(7, 12, 20, 0.85);
|
||||
--Tooltip-body-color: var(--text-color);
|
||||
--Tooltip-body-color--dark: var(--white);
|
||||
--Tooltip-body-paddingX: var(--gap-sm);
|
||||
--Tooltip-body-paddingX: var(--gap-base);
|
||||
--Tooltip-body-paddingY: var(--gap-sm);
|
||||
--Tooltip-borderColor: var(--borderColor);
|
||||
--Tooltip-borderRadius: var(--borderRadiusLg);
|
||||
--Tooltip-borderWidth: var(--borderWidth);
|
||||
--Tooltip-boxShadow: var(--boxShadow);
|
||||
--Tooltip-boxShadow: var(--boxTooltipShadow);
|
||||
--Tooltip-boxShadow--dark: 0 2px 8px 0 rgba(7, 12, 20, 0.12);
|
||||
--Tooltip-fontSize: var(--fontSizeSm);
|
||||
--Tooltip-fontWeight: var(--fontWeightMd);
|
||||
--Tooltip-maxWidth: #{px2rem(240px)};
|
||||
--Tooltip-minWidth: auto;
|
||||
--Tooltip-title-fontWeight: bold;
|
||||
@ -1468,8 +1471,8 @@
|
||||
--Tooltip-title-borderBottom-color: #{darken(darken($white, 3%), 5%)};
|
||||
--Tooltip-title-color: var(--text--loud-color);
|
||||
--Tooltip-title-color--dark: var(--white);
|
||||
--Tooltip-title-paddingX: var(--gap-sm);
|
||||
--Tooltip-title-paddingY: var(--gap-xs);
|
||||
--Tooltip-title-paddingX: var(--gap-base);
|
||||
--Tooltip-title-paddingY: var(--gap-sm);
|
||||
|
||||
--Transfer-title-bg: #f6f8f8;
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
z-index: $zindex-tooltip;
|
||||
word-wrap: break-word;
|
||||
background: var(--Tooltip-bg);
|
||||
border: var(--Tooltip-borderWidth) solid var(--Tooltip-borderColor);
|
||||
box-shadow: var(--Tooltip-boxShadow);
|
||||
|
||||
&-arrow {
|
||||
@ -49,7 +48,6 @@
|
||||
|
||||
.#{$ns}Tooltip-arrow::before {
|
||||
bottom: 0;
|
||||
border-top-color: var(--Tooltip-arrow-outerColor);
|
||||
}
|
||||
|
||||
.#{$ns}Tooltip-arrow::after {
|
||||
@ -77,7 +75,6 @@
|
||||
|
||||
.#{$ns}Tooltip-arrow::before {
|
||||
left: 0;
|
||||
border-right-color: var(--Tooltip-arrow-outerColor);
|
||||
}
|
||||
|
||||
.#{$ns}Tooltip-arrow::after {
|
||||
@ -103,7 +100,6 @@
|
||||
|
||||
.#{$ns}Tooltip-arrow::before {
|
||||
top: 0;
|
||||
border-bottom-color: var(--Tooltip-arrow-outerColor);
|
||||
}
|
||||
|
||||
.#{$ns}Tooltip-arrow::after {
|
||||
@ -146,7 +142,6 @@
|
||||
|
||||
.#{$ns}Tooltip-arrow::before {
|
||||
right: 0;
|
||||
border-left-color: var(--Tooltip-arrow-outerColor);
|
||||
}
|
||||
|
||||
.#{$ns}Tooltip-arrow::after {
|
||||
@ -156,13 +151,11 @@
|
||||
}
|
||||
|
||||
&-title {
|
||||
padding: var(--Tooltip-title-paddingY) var(--Tooltip-title-paddingX);
|
||||
padding: var(--Tooltip-title-paddingY) var(--Tooltip-title-paddingX) 0;
|
||||
margin-bottom: 0; // Reset the default from Reboot
|
||||
font-size: var(--fontSizeBase);
|
||||
color: var(--Tooltip-title-color);
|
||||
background: var(--Tooltip-title-bg);
|
||||
border-bottom: var(--Tooltip-borderWidth) solid
|
||||
var(--Tooltip-title-borderBottom-color);
|
||||
font-weight: var(--Tooltip-fontWeight);
|
||||
border-top-left-radius: calc(
|
||||
var(--Tooltip-borderRadius) - var(--Tooltip-borderWidth)
|
||||
);
|
||||
@ -179,6 +172,8 @@
|
||||
&-body {
|
||||
color: var(--Tooltip-body-color);
|
||||
padding: var(--Tooltip-body-paddingY) var(--Tooltip-body-paddingX);
|
||||
word-break: break-all;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&--dark {
|
||||
|
@ -97,7 +97,8 @@ class Position extends React.Component<any, any> {
|
||||
overlay,
|
||||
target,
|
||||
container,
|
||||
this.props.containerPadding
|
||||
this.props.containerPadding,
|
||||
this.props.offset
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -173,7 +174,7 @@ interface OverlayProps {
|
||||
container?: React.ReactNode | Function;
|
||||
target?: React.ReactNode | Function;
|
||||
watchTargetSizeChange?: boolean;
|
||||
|
||||
offset?: [number, number];
|
||||
onEnter?(node: HTMLElement): any;
|
||||
onEntering?(node: HTMLElement): any;
|
||||
onEntered?(node: HTMLElement): any;
|
||||
@ -238,6 +239,7 @@ export default class Overlay extends React.Component<
|
||||
children,
|
||||
watchTargetSizeChange,
|
||||
transition: Transition,
|
||||
offset,
|
||||
...props
|
||||
} = this.props;
|
||||
|
||||
@ -259,7 +261,8 @@ export default class Overlay extends React.Component<
|
||||
containerPadding,
|
||||
target,
|
||||
placement,
|
||||
shouldUpdatePosition
|
||||
shouldUpdatePosition,
|
||||
offset
|
||||
}}
|
||||
ref={this.positionRef}
|
||||
>
|
||||
|
@ -18,18 +18,23 @@ interface TooltipProps extends React.HTMLProps<HTMLDivElement> {
|
||||
style?: any;
|
||||
arrowProps?: any;
|
||||
placement?: string;
|
||||
showArrow?: boolean;
|
||||
tooltipTheme?: string;
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
export class Tooltip extends React.Component<TooltipProps> {
|
||||
static defaultProps = {
|
||||
className: ''
|
||||
className: '',
|
||||
tooltipTheme: 'light',
|
||||
showArrow: true
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
classPrefix: ns,
|
||||
className,
|
||||
tooltipTheme,
|
||||
title,
|
||||
children,
|
||||
arrowProps,
|
||||
@ -41,6 +46,7 @@ export class Tooltip extends React.Component<TooltipProps> {
|
||||
positionTop,
|
||||
classnames: cx,
|
||||
activePlacement,
|
||||
showArrow,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
...rest
|
||||
@ -52,14 +58,17 @@ export class Tooltip extends React.Component<TooltipProps> {
|
||||
className={cx(
|
||||
`Tooltip`,
|
||||
activePlacement ? `Tooltip--${activePlacement}` : '',
|
||||
className
|
||||
className,
|
||||
`Tooltip--${tooltipTheme === 'dark' ? 'dark' : 'light'}`
|
||||
)}
|
||||
style={style}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
role="tooltip"
|
||||
>
|
||||
<div className={cx(`Tooltip-arrow`)} {...arrowProps} />
|
||||
{showArrow ? (
|
||||
<div className={cx(`Tooltip-arrow`)} {...arrowProps} />
|
||||
) : null}
|
||||
{title ? <div className={cx('Tooltip-title')}>{title}</div> : null}
|
||||
<div className={cx('Tooltip-body')}>{children}</div>
|
||||
</div>
|
||||
|
@ -11,21 +11,78 @@ import {findDOMNode} from 'react-dom';
|
||||
import Tooltip from './Tooltip';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
import Overlay from './Overlay';
|
||||
|
||||
export interface TooltipObject {
|
||||
title?: string;
|
||||
content?: string;
|
||||
render?: () => JSX.Element;
|
||||
dom?: JSX.Element;
|
||||
}
|
||||
import {isObject} from '../utils/helper';
|
||||
|
||||
export type Trigger = 'hover' | 'click' | 'focus';
|
||||
|
||||
export interface TooltipObject {
|
||||
/**
|
||||
* 文字提示标题
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
* 文字提示内容
|
||||
*/
|
||||
content?: string;
|
||||
/**
|
||||
* 浮层出现位置
|
||||
*/
|
||||
placement?: 'top' | 'right' | 'bottom' | 'left';
|
||||
/**
|
||||
* 主题样式
|
||||
*/
|
||||
tooltipTheme?: 'light' | 'dark';
|
||||
/**
|
||||
* 浮层位置相对偏移量
|
||||
*/
|
||||
offset?: [number, number];
|
||||
/**
|
||||
* 内容区自定义样式
|
||||
*/
|
||||
style?: React.CSSProperties;
|
||||
/**
|
||||
* 是否展示浮层指向箭头
|
||||
*/
|
||||
showArrow?: boolean;
|
||||
/**
|
||||
* 是否禁用提示
|
||||
*/
|
||||
disabled?: boolean;
|
||||
/**
|
||||
* 浮层延迟显示时间, 单位 ms
|
||||
*/
|
||||
mouseEnterDelay?: number;
|
||||
/**
|
||||
* 浮层延迟隐藏时间, 单位 ms
|
||||
*/
|
||||
mouseLeaveDelay?: number;
|
||||
/**
|
||||
* 浮层内容可通过JSX渲染
|
||||
*/
|
||||
children?: () => JSX.Element | JSX.Element;
|
||||
/**
|
||||
* 挂载容器元素
|
||||
*/
|
||||
container?: React.ReactNode;
|
||||
/**
|
||||
* 浮层触发方式
|
||||
*/
|
||||
trigger?: Trigger | Array<Trigger>;
|
||||
/**
|
||||
* 是否点击非内容区域关闭提示,默认为true
|
||||
*/
|
||||
rootClose?: boolean;
|
||||
/**
|
||||
* 文字提示浮层CSS类名
|
||||
*/
|
||||
tooltipClassName?: string;
|
||||
}
|
||||
|
||||
export interface TooltipWrapperProps {
|
||||
tooltip?: string | TooltipObject;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
placement: 'top' | 'right' | 'bottom' | 'left';
|
||||
tooltip?: string | TooltipObject;
|
||||
container?: React.ReactNode;
|
||||
trigger: Trigger | Array<Trigger>;
|
||||
rootClose: boolean;
|
||||
@ -109,15 +166,26 @@ export class TooltipWrapper extends React.Component<
|
||||
handleShow() {
|
||||
this.timer && clearTimeout(this.timer);
|
||||
waitToHide && waitToHide();
|
||||
this.show();
|
||||
const tooltip = this.props.tooltip;
|
||||
if (isObject(tooltip)) {
|
||||
const {mouseEnterDelay = 0} = tooltip as TooltipObject;
|
||||
this.timer = setTimeout(this.show, mouseEnterDelay);
|
||||
} else {
|
||||
this.timer = setTimeout(this.show, 0);
|
||||
}
|
||||
}
|
||||
|
||||
handleHide() {
|
||||
clearTimeout(this.timer);
|
||||
const {delay} = this.props;
|
||||
const {delay, tooltip} = this.props;
|
||||
|
||||
waitToHide = this.hide.bind(this);
|
||||
this.timer = setTimeout(this.hide, delay);
|
||||
if (isObject(tooltip)) {
|
||||
const {mouseLeaveDelay = 300} = tooltip as TooltipObject;
|
||||
this.timer = setTimeout(this.hide, mouseLeaveDelay);
|
||||
} else {
|
||||
this.timer = setTimeout(this.hide, delay);
|
||||
}
|
||||
}
|
||||
|
||||
handleFocus(e: any) {
|
||||
@ -161,22 +229,42 @@ export class TooltipWrapper extends React.Component<
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
|
||||
const child = React.Children.only(props.children);
|
||||
if (!props.tooltip) {
|
||||
return child;
|
||||
}
|
||||
|
||||
// tooltip 对象内属性优先级更高
|
||||
const tooltipObj: TooltipObject = {
|
||||
placement: props.placement,
|
||||
container: props.container,
|
||||
trigger: props.trigger,
|
||||
rootClose: props.rootClose,
|
||||
tooltipClassName: props.tooltipClassName,
|
||||
style: props.style,
|
||||
mouseLeaveDelay: props.delay,
|
||||
...(typeof props.tooltip === 'string'
|
||||
? {content: props.tooltip}
|
||||
: props.tooltip)
|
||||
};
|
||||
|
||||
const {
|
||||
tooltip,
|
||||
children,
|
||||
title,
|
||||
content,
|
||||
placement,
|
||||
container,
|
||||
trigger,
|
||||
rootClose,
|
||||
tooltipClassName,
|
||||
style
|
||||
} = this.props;
|
||||
|
||||
const child = React.Children.only(children);
|
||||
|
||||
if (!tooltip) {
|
||||
return child;
|
||||
}
|
||||
style,
|
||||
disabled = false,
|
||||
offset,
|
||||
tooltipTheme = 'light',
|
||||
showArrow = true,
|
||||
children
|
||||
} = tooltipObj;
|
||||
|
||||
const childProps: any = {
|
||||
key: 'target'
|
||||
@ -204,31 +292,30 @@ export class TooltipWrapper extends React.Component<
|
||||
<Overlay
|
||||
key="overlay"
|
||||
target={this.getTarget}
|
||||
show={this.state.show}
|
||||
show={this.state.show && !disabled}
|
||||
onHide={this.handleHide}
|
||||
rootClose={rootClose}
|
||||
placement={placement}
|
||||
container={container}
|
||||
offset={Array.isArray(offset) ? offset : [0, 0]}
|
||||
>
|
||||
<Tooltip
|
||||
title={typeof tooltip !== 'string' ? tooltip.title : undefined}
|
||||
title={typeof title === 'string' ? title : undefined}
|
||||
style={style}
|
||||
className={tooltipClassName}
|
||||
onMouseEnter={~triggers.indexOf('hover') && this.handleMouseOver}
|
||||
onMouseLeave={~triggers.indexOf('hover') && this.handleMouseOut}
|
||||
tooltipTheme={tooltipTheme}
|
||||
showArrow={showArrow}
|
||||
onMouseEnter={
|
||||
~triggers.indexOf('hover') ? this.handleMouseOver : () => {}
|
||||
}
|
||||
onMouseLeave={
|
||||
~triggers.indexOf('hover') ? this.handleMouseOut : () => {}
|
||||
}
|
||||
>
|
||||
{tooltip && (tooltip as TooltipObject).render ? (
|
||||
this.state.show ? (
|
||||
(tooltip as TooltipObject).render!()
|
||||
) : null
|
||||
) : tooltip && (tooltip as TooltipObject).dom ? (
|
||||
(tooltip as TooltipObject).dom!
|
||||
{children ? (
|
||||
<>{typeof children === 'function' ? children() : children}</>
|
||||
) : (
|
||||
<Html
|
||||
html={
|
||||
typeof tooltip === 'string' ? tooltip : tooltip.content || ''
|
||||
}
|
||||
/>
|
||||
<Html html={typeof content === 'string' ? content : ''} />
|
||||
)}
|
||||
</Tooltip>
|
||||
</Overlay>
|
||||
|
@ -6,7 +6,7 @@ import {escapeHtml} from '../utils/tpl-builtin';
|
||||
import {buildStyle} from '../utils/style';
|
||||
import {TooltipWrapper as TooltipWrapperComp} from '../components';
|
||||
|
||||
import type {Trigger} from '../components/TooltipWrapper';
|
||||
import type {Trigger, TooltipObject} from '../components/TooltipWrapper';
|
||||
|
||||
export interface TooltipWrapperSchema extends BaseSchema {
|
||||
/**
|
||||
@ -20,7 +20,12 @@ export interface TooltipWrapperSchema extends BaseSchema {
|
||||
title?: string;
|
||||
|
||||
/**
|
||||
* 文字提示
|
||||
* 文字提示内容,兼容 tooltip,但建议通过 content 来实现提示内容
|
||||
*/
|
||||
content?: string;
|
||||
|
||||
/**
|
||||
* @deprecated 文字提示内容
|
||||
*/
|
||||
tooltip?: string;
|
||||
|
||||
@ -29,15 +34,35 @@ export interface TooltipWrapperSchema extends BaseSchema {
|
||||
*/
|
||||
placement?: 'top' | 'right' | 'bottom' | 'left';
|
||||
|
||||
/**
|
||||
* 浮层位置相对偏移量
|
||||
*/
|
||||
offset?: [number, number];
|
||||
|
||||
/**
|
||||
* 是否展示浮层指向箭头
|
||||
*/
|
||||
showArrow?: boolean;
|
||||
|
||||
/**
|
||||
* 是否禁用提示
|
||||
*/
|
||||
disabled?: boolean;
|
||||
|
||||
/**
|
||||
* 浮层触发方式,默认为hover
|
||||
*/
|
||||
trigger?: Trigger | Array<Trigger>;
|
||||
|
||||
/**
|
||||
* 浮层隐藏延迟时间,单位ms,默认0
|
||||
* 浮层延迟显示时间, 单位 ms
|
||||
*/
|
||||
delay?: number;
|
||||
|
||||
mouseEnterDelay?: number;
|
||||
/**
|
||||
* 浮层延迟隐藏时间, 单位 ms
|
||||
*/
|
||||
mouseLeaveDelay?: number;
|
||||
|
||||
/**
|
||||
* 是否点击非内容区域关闭提示,默认为true
|
||||
@ -60,7 +85,7 @@ export interface TooltipWrapperSchema extends BaseSchema {
|
||||
inline?: boolean;
|
||||
|
||||
/**
|
||||
* 浮层主题色,默认为light
|
||||
* 主题样式, 默认为light
|
||||
*/
|
||||
tooltipTheme?: 'light' | 'dark';
|
||||
|
||||
@ -97,6 +122,7 @@ export interface TooltipWrapperProps extends RendererProps {
|
||||
/**
|
||||
* 文字提示
|
||||
*/
|
||||
content?: string;
|
||||
tooltip?: string;
|
||||
/**
|
||||
* 文字提示位置
|
||||
@ -105,7 +131,11 @@ export interface TooltipWrapperProps extends RendererProps {
|
||||
inline?: boolean;
|
||||
trigger: Trigger | Array<Trigger>;
|
||||
rootClose?: boolean;
|
||||
delay?: number;
|
||||
showArrow?: boolean;
|
||||
offset?: [number, number];
|
||||
disabled?: boolean;
|
||||
mouseEnterDelay?: number;
|
||||
mouseLeaveDelay?: number;
|
||||
container?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
tooltipStyle?: React.CSSProperties;
|
||||
@ -124,7 +154,8 @@ export default class TooltipWrapper extends React.Component<
|
||||
| 'placement'
|
||||
| 'trigger'
|
||||
| 'rootClose'
|
||||
| 'delay'
|
||||
| 'mouseEnterDelay'
|
||||
| 'mouseLeaveDelay'
|
||||
| 'inline'
|
||||
| 'wrap'
|
||||
| 'tooltipTheme'
|
||||
@ -132,7 +163,8 @@ export default class TooltipWrapper extends React.Component<
|
||||
placement: 'top',
|
||||
trigger: 'hover',
|
||||
rootClose: true,
|
||||
delay: 0,
|
||||
mouseEnterDelay: 0,
|
||||
mouseLeaveDelay: 200,
|
||||
inline: false,
|
||||
wrap: false,
|
||||
tooltipTheme: 'light'
|
||||
@ -172,41 +204,45 @@ export default class TooltipWrapper extends React.Component<
|
||||
|
||||
render() {
|
||||
const {
|
||||
tooltipClassName,
|
||||
classPrefix: ns,
|
||||
classnames: cx,
|
||||
tooltipClassName,
|
||||
tooltipTheme,
|
||||
container,
|
||||
placement,
|
||||
rootClose,
|
||||
tooltipStyle,
|
||||
title,
|
||||
content,
|
||||
tooltip,
|
||||
delay,
|
||||
mouseEnterDelay,
|
||||
mouseLeaveDelay,
|
||||
trigger,
|
||||
tooltipTheme,
|
||||
offset,
|
||||
showArrow,
|
||||
disabled,
|
||||
data
|
||||
} = this.props;
|
||||
|
||||
const tooltipObj = {
|
||||
title: escapeHtml(filter(title, data)),
|
||||
content: escapeHtml(filter(tooltip, data))
|
||||
const tooltipObj: TooltipObject = {
|
||||
title: filter(title, data),
|
||||
content: filter(content || tooltip, data),
|
||||
style: buildStyle(tooltipStyle, data),
|
||||
placement,
|
||||
trigger,
|
||||
rootClose,
|
||||
container,
|
||||
tooltipTheme,
|
||||
tooltipClassName,
|
||||
mouseEnterDelay,
|
||||
mouseLeaveDelay,
|
||||
offset,
|
||||
showArrow,
|
||||
disabled
|
||||
};
|
||||
|
||||
return (
|
||||
<TooltipWrapperComp
|
||||
classPrefix={ns}
|
||||
classnames={cx}
|
||||
style={buildStyle(tooltipStyle, data)}
|
||||
placement={placement}
|
||||
tooltip={tooltipObj}
|
||||
trigger={trigger}
|
||||
rootClose={rootClose}
|
||||
delay={delay}
|
||||
container={container}
|
||||
tooltipClassName={cx(tooltipClassName, {
|
||||
'Tooltip--dark': tooltipTheme === 'dark'
|
||||
})}
|
||||
>
|
||||
<TooltipWrapperComp classPrefix={ns} classnames={cx} tooltip={tooltipObj}>
|
||||
{this.renderBody()}
|
||||
</TooltipWrapperComp>
|
||||
);
|
||||
|
@ -82,7 +82,8 @@ export function calculatePosition(
|
||||
overlayNode: any,
|
||||
target: HTMLElement,
|
||||
container: any,
|
||||
padding: any = 0
|
||||
padding: any = 0,
|
||||
customOffset: [number, number] = [0, 0]
|
||||
) {
|
||||
const childOffset: any =
|
||||
container.tagName === 'BODY'
|
||||
@ -126,14 +127,14 @@ export function calculatePosition(
|
||||
atX === 'left'
|
||||
? childOffset.left
|
||||
: atX === 'right'
|
||||
? childOffset.left + childOffset.width
|
||||
: childOffset.left + childOffset.width / 2;
|
||||
? childOffset.left + childOffset.width
|
||||
: childOffset.left + childOffset.width / 2;
|
||||
positionTop =
|
||||
atY === 'top'
|
||||
? childOffset.top
|
||||
: atY === 'bottom'
|
||||
? childOffset.top + childOffset.height
|
||||
: childOffset.top + childOffset.height / 2;
|
||||
? childOffset.top + childOffset.height
|
||||
: childOffset.top + childOffset.height / 2;
|
||||
|
||||
positionLeft -=
|
||||
myX === 'left' ? 0 : myX === 'right' ? overlayWidth : overlayWidth / 2;
|
||||
@ -141,8 +142,8 @@ export function calculatePosition(
|
||||
myY === 'top'
|
||||
? 0
|
||||
: myY === 'bottom'
|
||||
? overlayHeight
|
||||
: overlayHeight / 2;
|
||||
? overlayHeight
|
||||
: overlayHeight / 2;
|
||||
|
||||
// 如果还有其他可选项,则做位置判断,是否在可视区域,不完全在则继续看其他定位情况。
|
||||
if (tests.length) {
|
||||
@ -215,12 +216,12 @@ export function calculatePosition(
|
||||
`calcOverlayPosition(): No such placement of "${placement}" found.`
|
||||
);
|
||||
}
|
||||
|
||||
const [offSetX = 0, offSetY = 0] = customOffset;
|
||||
return {
|
||||
positionLeft: positionLeft / scaleX,
|
||||
positionTop: positionTop / scaleY,
|
||||
arrowOffsetLeft: arrowOffsetLeft / scaleX,
|
||||
arrowOffsetTop: arrowOffsetTop / scaleY,
|
||||
positionLeft: (positionLeft + offSetX) / scaleX,
|
||||
positionTop: (positionTop + offSetY) / scaleY,
|
||||
arrowOffsetLeft: (arrowOffsetLeft + offSetX) / scaleX,
|
||||
arrowOffsetTop: (arrowOffsetTop + offSetY) / scaleY,
|
||||
activePlacement
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user