diff --git a/packages/components/dialog/memo-children.tsx b/packages/components/dialog/memo-children.tsx
new file mode 100644
index 0000000..34e386d
--- /dev/null
+++ b/packages/components/dialog/memo-children.tsx
@@ -0,0 +1,15 @@
+/*
+ * @Date: 2024-09-08 09:47:51
+ * @Description: Modify here please
+ */
+import * as React from "react";
+
+export type MemoChildrenProps = {
+ shouldUpdate: boolean;
+ children: React.ReactNode;
+};
+
+export default React.memo(
+ ({ children }: MemoChildrenProps) => children as React.ReactElement,
+ (_, { shouldUpdate }) => !shouldUpdate
+);
diff --git a/packages/components/dialog/type.ts b/packages/components/dialog/type.ts
index 53fc197..e26ce64 100644
--- a/packages/components/dialog/type.ts
+++ b/packages/components/dialog/type.ts
@@ -29,7 +29,9 @@ export interface IDialogProps extends IOverlayProps, IDialogContentProps {
lockScroll?: boolean;
/** 是否支持键盘 esc 关闭 */
keyboard?: boolean;
- /** 动画持续时间,当你想修改自带的动画效果时,这个很有用 */
+ /** 执行的动画的类名 */
+ transitionName?: string;
+ /** 执行动画的时长,当你需要自定义动画时,这个是很有用的 */
duration?: number;
/** 弹窗body内容部分,语义化结构className */
className?: string;
diff --git a/packages/components/tooltip/popup.tsx b/packages/components/tooltip/popup.tsx
index efbcf03..2772c87 100644
--- a/packages/components/tooltip/popup.tsx
+++ b/packages/components/tooltip/popup.tsx
@@ -46,7 +46,7 @@ const TooltipPopup = React.forwardRef
((pro
// 动画类名
const motionName = useMemo(() => {
- return transitionName || `${getPrefixCls()}-zoom-in-top`;
+ return transitionName || `${getPrefixCls()}-zoom-big-fast`;
}, [transitionName]);
// When the element has been removed from the DOM
diff --git a/packages/core/utils/dom.ts b/packages/core/utils/dom.ts
index 3e1a78a..412e252 100644
--- a/packages/core/utils/dom.ts
+++ b/packages/core/utils/dom.ts
@@ -37,3 +37,25 @@ export const getScrollBarWidth = (): number => {
export function canUseDom() {
return !!(typeof window !== "undefined" && window.document && window.document.createElement);
}
+
+export function contains(root: Node | null | undefined, n?: Node) {
+ if (!root) {
+ return false;
+ }
+
+ // Use native if support
+ if (root.contains) {
+ return root.contains(n);
+ }
+
+ // `document.contains` not support with IE11
+ let node = n;
+ while (node) {
+ if (node === root) {
+ return true;
+ }
+ node = node.parentNode;
+ }
+
+ return false;
+}
From 267941f74c601ccf651623ebf0a3c7c0dcf28b8b Mon Sep 17 00:00:00 2001
From: "PL196\\40380" <403802162@qq.com>
Date: Sun, 8 Sep 2024 19:48:06 +0800
Subject: [PATCH 2/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.docs/docs/libraries/popover.md | 104 ++++++++++++++++
.docs/docs/libraries/tooltip.md | 10 +-
.docs/style/components.scss | 5 +-
.docs/style/index.scss | 1 +
.docs/style/page.scss | 7 ++
packages/camelia/version.ts | 2 +-
.../components/_styles/common/transition.scss | 44 +++++++
packages/components/index.ts | 5 +-
packages/components/popover/index.tsx | 111 ++++++++++++++++++
packages/components/popover/style/index.scss | 37 ++++++
packages/components/popover/style/index.ts | 7 ++
packages/components/tooltip/popup-type.ts | 2 +-
packages/components/tooltip/popup.tsx | 2 +-
packages/components/tooltip/style/index.scss | 4 +-
packages/components/tooltip/tooltip-type.ts | 17 ++-
packages/components/tooltip/tooltip.tsx | 27 +++--
packages/components/tooltip/trigger-type.ts | 7 +-
packages/components/tooltip/trigger.tsx | 39 ++++--
packages/shared/use-click-away/index.ts | 1 -
19 files changed, 396 insertions(+), 36 deletions(-)
create mode 100644 .docs/docs/libraries/popover.md
create mode 100644 packages/components/popover/index.tsx
create mode 100644 packages/components/popover/style/index.scss
create mode 100644 packages/components/popover/style/index.ts
diff --git a/.docs/docs/libraries/popover.md b/.docs/docs/libraries/popover.md
new file mode 100644
index 0000000..5395b8f
--- /dev/null
+++ b/.docs/docs/libraries/popover.md
@@ -0,0 +1,104 @@
+---
+order: 4
+group:
+ title: 数据展示
+ order: 3
+---
+
+# Popover 气泡卡片
+
+Popover 是在 Tooltip 基础上开发出来的。 因此对于重复属性,请参考 Tooltip 的文档,在此文档中不做详尽解释。
+
+## 基础用法
+1. trigger 属性被用来决定 popover 的触发方式,支持的触发方式: `hover` `click` 如果你想手动控制它,可以设置 visible 属性。
+2. 最简单的用法,浮层的大小由内容区域决定。
+
+```tsx
+import React from 'react';
+import { Button, Popover } from 'camelia';
+
+const content = (
+
+
There is a lot of content
+
There is a lot of content
+
+);
+
+const App: React.FC = () => (
+ <>
+
+
+
+
+
+
+ >
+);
+
+export default App;
+```
+
+## 虚拟触发
+
+1. 可以由虚拟元素触发,这个功能就很适合使用在触发元素和展示内容元素是分开的场景
+2. 结合visible,你可以做的主动控制Popover
+
+```tsx
+import React, { useState, useRef } from 'react';
+import { Button, Popover } from 'camelia';
+import { useClickAway } from "camelia/shared";
+
+const content = (
+
+
There is a lot of content
+
There is a lot of content
+
+);
+
+const App: React.FC = () => {
+ const [clicked, setClicked] = useState(false);
+ const [enable, setEnable] = useState(false);
+
+ const virtualRef = useRef(null)
+ const popoverRef = useRef(null)
+
+ // 点击弹窗外面主动取消
+ useClickAway(() => {
+ setClicked(false)
+ }, popoverRef.current?.popupRef, {
+ enable
+ });
+
+ return(
+ <>
+
+ {
+ setEnable(v)
+ }}
+ />
+ >
+ )
+}
+
+export default App;
+```
+
+## API
+
+| 参数 | 说明 | 类型 | 默认值 | 版本 |
+| ------- | -------- | ---------------------------- | ------ | ---- |
+| content | 卡片内容 | ReactNode \| () => ReactNode | - | |
+| title | 卡片标题 | ReactNode \| () => ReactNode | - | |
+
+更多属性请参考 [Tooltip](http://cameliya.cn/libraries/tooltip#api)。
+
+## 注意
+
+请确保 `Popover` 的子元素能接受 `onMouseEnter` `onMouseLeave` `onClick` 事件。
diff --git a/.docs/docs/libraries/tooltip.md b/.docs/docs/libraries/tooltip.md
index a05bdaf..40c9a4e 100644
--- a/.docs/docs/libraries/tooltip.md
+++ b/.docs/docs/libraries/tooltip.md
@@ -101,21 +101,23 @@ export default App;
| transitionName | [动画名称, 请查看描述](https://reactcommunity.org/react-transition-group/css-transition) | string | — |
| duration | 执行动画的时长(以毫秒为单位)的 | number | 200 |
| disabled | 是否禁止 | boolean | false |
-| destroyTooltipOnHide | 关闭后是否销毁 Tooltip | boolean | false |
+| destroyTooltipOnHide | 关闭后是否销毁 Tooltip | boolean | true |
| overlayClassName | 卡片类名 | string | — |
| overlayStyle | 卡片style | CSSProperties | — |
| zIndex | 设置 Tooltip 的 z-index | number | — |
| visible | 受控模式,来控制它的显示与关闭 | boolean | — |
| getPopupContainer | 浮层渲染父节点,默认渲染到 body 上 | (triggerNode:HTMLElement) => void | — |
| showArrow | tooltip 的内容是否有箭头 | boolean | true |
-| onShow | 显示时的回调 | () => void | — |
-| onHide | 隐藏时的回调 | () => void | — |
+| virtualTriggering | 用来标识虚拟触发是否被启用 | boolean | false |
+| virtualRef | 标识虚拟触发时的触发元素 | MutableRefObject< HTMLElement > | — |
+| onOpenChange | 显示隐藏的回调 | (open: boolean) => void | — |
### Methods
| 名称 | 说明 | 类型 |
| ------------ | -------------------------------------------------------------------------------- | ---------------------------- |
| tooltipRef | tooltip Component | object |
+| popupRef | 获取popup的ref, 可能有些业务场景是想要获取popup节点的 | object |
| onOpen | 控制显示状态 | Function |
| onClose | 控制隐藏状态, 可以传递一个time来覆盖hideAfterTime,为0时立马关闭弹窗 | Function `(time) => void` |
-| updatePopup | 使用更新位置 | Function
+| updatePopup | 使用更新位置 | Function |
diff --git a/.docs/style/components.scss b/.docs/style/components.scss
index f6f87ed..294dc19 100644
--- a/.docs/style/components.scss
+++ b/.docs/style/components.scss
@@ -4,10 +4,11 @@
@use "../../packages/components/checkbox/style/index.scss" as *;
@use "../../packages/components/dialog/style/index.scss" as *;
@use "../../packages/components/image/style/index.scss" as *;
+ @use "../../packages/components/input/style/index.scss" as *;
+ @use "../../packages/components/img-captcha/style/index.scss" as *;
@use "../../packages/components/message/style/index.scss" as *;
+ @use "../../packages/components/popover/style/index.scss" as *;
@use "../../packages/components/prompt/style/index.scss" as *;
- @use "../../packages/components/img-captcha/style/index.scss" as *;
- @use "../../packages/components/input/style/index.scss" as *;
@use "../../packages/components/tag/style/index.scss" as *;
@use "../../packages/components/tooltip/style/index.scss" as *;
@use "../../packages/components/_internal/wave/style/index.scss" as *;
diff --git a/.docs/style/index.scss b/.docs/style/index.scss
index 49c6d72..d880eef 100644
--- a/.docs/style/index.scss
+++ b/.docs/style/index.scss
@@ -6,3 +6,4 @@
// 引入页面组件的样式
@import "./page.scss";
+
diff --git a/.docs/style/page.scss b/.docs/style/page.scss
index 8aa26a5..fd02af7 100644
--- a/.docs/style/page.scss
+++ b/.docs/style/page.scss
@@ -1,5 +1,12 @@
@use "../.dumi/var.scss" as *;
+.layout-init-box {
+ p {
+ margin: 0;
+ }
+}
+
+
.site-t2vb78 .icon-item {
:hover {
background-color: #2b2b2c;
diff --git a/packages/camelia/version.ts b/packages/camelia/version.ts
index 333a7e4..f14110c 100644
--- a/packages/camelia/version.ts
+++ b/packages/camelia/version.ts
@@ -6,4 +6,4 @@
* "当你在使用 pnpm 处理多包依赖时,如果本地包的版本与远程版本完全匹配,
* 则 pnpm 会默认使用本地包覆盖远程包,无论远程包的版本是更新的还是旧的。"
*/
-export const version = "1.1.3";
+export const version = "1.1.4";
diff --git a/packages/components/_styles/common/transition.scss b/packages/components/_styles/common/transition.scss
index 94bc560..7d7c574 100644
--- a/packages/components/_styles/common/transition.scss
+++ b/packages/components/_styles/common/transition.scss
@@ -78,6 +78,50 @@
}
}
+/*
+* 放大顶部
+*/
+.#{$namespace}-zoom-in-top-enter-active {
+ animation-name: #{$namespace}-zoom-in-top-in;
+ animation-duration: 0.2s;
+ animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
+ transform-origin: center top;
+ &[data-popper-placement^="top"] {
+ transform-origin: center bottom;
+ }
+}
+.#{$namespace}-zoom-in-top-exit-active {
+ animation-name: #{$namespace}-zoom-in-top-out;
+ animation-duration: 0.2s;
+ animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
+ transform-origin: center top;
+ &[data-popper-placement^="top"] {
+ transform-origin: center bottom;
+ }
+}
+@keyframes #{$namespace}-zoom-in-top-in {
+ 0% {
+ transform: scaleY(0.8);
+ opacity: 0;
+ }
+
+ 100% {
+ transform: scaleY(1);
+ opacity: 1;
+ }
+}
+@keyframes #{$namespace}-zoom-in-top-out {
+ 0% {
+ transform: scaleY(1);
+ opacity: 1;
+ }
+
+ 100% {
+ transform: scaleY(0.8);
+ opacity: 0;
+ }
+}
+
/*
* 淡入按比例放大 --- select
*/
diff --git a/packages/components/index.ts b/packages/components/index.ts
index 8bdf630..f84d355 100644
--- a/packages/components/index.ts
+++ b/packages/components/index.ts
@@ -28,7 +28,10 @@ export { default as Dialog } from "./dialog";
export type { IDialogProps } from "./dialog";
export { default as Tooltip } from "./tooltip";
-export type { ITooltipProps } from "./tooltip";
+export type { ITooltipProps, ITooltipRef } from "./tooltip";
+
+export { default as Popover } from "./popover";
+export type { IPopoverProps } from "./popover";
// Plugin
export { default as message } from "./message";
diff --git a/packages/components/popover/index.tsx b/packages/components/popover/index.tsx
new file mode 100644
index 0000000..69b2366
--- /dev/null
+++ b/packages/components/popover/index.tsx
@@ -0,0 +1,111 @@
+/*
+ * @Date: 2024-09-08 13:59:29
+ * @Description: Modify here please
+ */
+import React, { useContext, useMemo, cloneElement, createRef } from "react";
+import { ConfigContext } from "../config-provider";
+import { useNamespace, KeyCode, composeRef } from "@camelia/core";
+import type { ITooltipProps, ITooltipRef } from "../tooltip";
+import Tooltip from "../tooltip";
+
+export interface IPopoverProps extends ITooltipProps {
+ title?: React.ReactNode | (() => React.ReactNode);
+ content?: React.ReactNode | (() => React.ReactNode);
+}
+
+interface OverlayProps {
+ prefixCls?: string;
+ title?: React.ReactNode;
+ content?: React.ReactNode;
+}
+
+const getRenderNode = (propValue?: T): React.ReactNode => {
+ if (!propValue) {
+ return null;
+ }
+
+ return typeof propValue === "function" ? propValue() : propValue;
+};
+
+const Overlay: React.FC = ({ title, content, prefixCls }) => {
+ if (!title && !content) {
+ return null;
+ }
+ return (
+ <>
+ {title && {title}
}
+ {content && {content}
}
+ >
+ );
+};
+
+const Popover = React.forwardRef((props, ref) => {
+ const {
+ title,
+ content,
+ virtualRef,
+ overlayClassName,
+ virtualTriggering,
+ placement = "top",
+ effect = "",
+ trigger = "hover",
+ children,
+ destroyTooltipOnHide = false,
+ overlayStyle = {},
+ ...otherProps
+ } = props;
+
+ const { getPrefixCls } = useContext(ConfigContext);
+ const ns = useNamespace("popover", getPrefixCls());
+
+ const internalRef = createRef();
+ const PopoverRef = composeRef(ref, internalRef);
+
+ // 动画类名
+ const motionName = useMemo(() => {
+ return otherProps.transitionName || `${getPrefixCls()}-zoom-big`;
+ }, [otherProps.transitionName]);
+
+ const titleNode = getRenderNode(title);
+ const contentNode = getRenderNode(content);
+
+ const onKeyDown = (e: React.KeyboardEvent) => {
+ if (e.keyCode === KeyCode.ESC) {
+ internalRef.current.onClose();
+ }
+ };
+
+ const triggerChild =
+ React.isValidElement(children) && !virtualTriggering
+ ? cloneElement(children as any, {
+ onKeyDown: (e: React.KeyboardEvent) => {
+ if (React.isValidElement(children)) {
+ children?.props.onKeyDown?.(e);
+ }
+ onKeyDown(e);
+ }
+ })
+ : null;
+
+ return (
+ : null}
+ transitionName={motionName}
+ >
+ {triggerChild}
+
+ );
+});
+
+export default Popover;
diff --git a/packages/components/popover/style/index.scss b/packages/components/popover/style/index.scss
new file mode 100644
index 0000000..1722e1a
--- /dev/null
+++ b/packages/components/popover/style/index.scss
@@ -0,0 +1,37 @@
+@use "../../_styles/core/mixins" as *;
+@use "../../_styles/common/var" as *;
+@use "../../_styles/core/css-var" as *;
+@use "../../_styles/core/function" as *;
+@use "../../_styles/core/config" as *;
+
+@include b(popover) {
+ --box-shadow-secondary: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12),
+ 0 9px 28px 8px rgba(0, 0, 0, 0.05);
+
+ &.#{$namespace}-popper {
+ border-radius: 0px;
+ }
+ .#{$namespace}-popper__content {
+ border-radius: 10px;
+ background-clip: padding-box;
+ background: #fff;
+ box-shadow: var(--box-shadow-secondary);
+ padding: 12px;
+ font-family: getCssVar("font-family");
+ }
+
+ .#{$namespace}-popper__arrow::before {
+ border: 1px solid #e4e7ed;
+ background: #fff;
+ }
+
+ @include e(title) {
+ margin-bottom: 8px;
+ color: rgba(0, 0, 0, 0.88);
+ font-weight: 600;
+ }
+
+ @include e(inner-content) {
+ color: rgba(0, 0, 0, 0.88);
+ }
+}
diff --git a/packages/components/popover/style/index.ts b/packages/components/popover/style/index.ts
new file mode 100644
index 0000000..3a1012a
--- /dev/null
+++ b/packages/components/popover/style/index.ts
@@ -0,0 +1,7 @@
+/*
+ * @Date: 2024-09-08 14:33:32
+ * @Description: Modify here please
+ */
+import "../../_styles/base.scss";
+import "../../tooltip/style";
+import "./index.scss";
diff --git a/packages/components/tooltip/popup-type.ts b/packages/components/tooltip/popup-type.ts
index 5ba9131..648543b 100644
--- a/packages/components/tooltip/popup-type.ts
+++ b/packages/components/tooltip/popup-type.ts
@@ -48,6 +48,6 @@ export interface ITooltipPopupProps {
}
export interface ITooltipPopupRef {
- /** updatePopper */
+ /** update Popper */
updatePopper: () => void;
}
diff --git a/packages/components/tooltip/popup.tsx b/packages/components/tooltip/popup.tsx
index 2772c87..ac0f340 100644
--- a/packages/components/tooltip/popup.tsx
+++ b/packages/components/tooltip/popup.tsx
@@ -69,7 +69,7 @@ const TooltipPopup = React.forwardRef((pro
return getParent(props.getPopupContainer, triggerRef.current);
}, [props.getPopupContainer, triggerRef.current]);
- const contentClass = [props.overlayClassName, ns.b(), ns.is(effect)];
+ const contentClass = [ns.b(), ns.is(effect), props.overlayClassName];
useImperativeHandle(ref, () => ({
updatePopper
diff --git a/packages/components/tooltip/style/index.scss b/packages/components/tooltip/style/index.scss
index 13ea8c5..fed8502 100644
--- a/packages/components/tooltip/style/index.scss
+++ b/packages/components/tooltip/style/index.scss
@@ -28,12 +28,12 @@
position: absolute;
width: 10px;
height: 10px;
- z-index: -1;
+ z-index: 1;
&:before {
position: absolute;
width: 10px;
height: 10px;
- z-index: -1;
+ z-index: 1;
content: " ";
transform: rotate(45deg);
background: #303133;
diff --git a/packages/components/tooltip/tooltip-type.ts b/packages/components/tooltip/tooltip-type.ts
index e875e76..7e26793 100644
--- a/packages/components/tooltip/tooltip-type.ts
+++ b/packages/components/tooltip/tooltip-type.ts
@@ -9,9 +9,11 @@ import type { ITooltipPopupProps } from "./popup-type";
import type { TooltipWrapInjectionContext } from "./utils";
export interface ITooltipProps
- extends ITooltipWrapProps,
- Omit,
- Omit {
+ extends Omit,
+ Omit,
+ Omit {
+ /** !!! This is a trigger node, which does not need to be passed because it can be passed after the virtual node */
+ children?: React.ReactNode;
/** 主动控制,不在受trigger的值影响 */
visible?: boolean | null;
/** 提示文字节点 */
@@ -22,12 +24,21 @@ export interface ITooltipProps
hideAfterTime?: number;
/** 出现延迟,以毫秒为单位 */
showAfterTime?: number;
+ /** 显示隐藏的回调 */
+ onOpenChange?: (open: boolean) => void;
}
export interface ITooltipRef {
+ /** tooltip Component */
tooltipRef: MutableRefObject;
+ /** 获取popup的ref */
+ popupRef: MutableRefObject;
+ /** open Popup */
onOpen: (time?: number) => void;
+ /** close Popup */
onClose: (time?: number) => void;
+ /** update Popup */
updatePopup: () => void;
+ /** 验证当前焦点目标是--提示内容中的节点 */
isFocusInsideContent: (event?: FocusEvent) => void;
}
diff --git a/packages/components/tooltip/tooltip.tsx b/packages/components/tooltip/tooltip.tsx
index d43865c..eff95ea 100644
--- a/packages/components/tooltip/tooltip.tsx
+++ b/packages/components/tooltip/tooltip.tsx
@@ -22,12 +22,12 @@ const Tooltip = React.forwardRef((props, ref) => {
role = "tooltip",
trigger = "hover",
effect = "dark",
- destroyTooltipOnHide = false,
+ destroyTooltipOnHide = true,
showArrow = true,
placement = "top",
strategy = "absolute",
disabled,
- children,
+ children: TriggerNode,
title,
offset,
overlay,
@@ -101,14 +101,19 @@ const Tooltip = React.forwardRef((props, ref) => {
// pop show
const onContentShow = () => {
- restProps.onShow?.();
- // Start monitoring external clicks
- start();
+ restProps.onOpenChange?.(true);
+ /**
+ * Start monitoring external clicks
+ * !! if: When actively controlling pop outside, do not turn on monitoring
+ */
+ if (!stopWhenControlledOrDisabled()) {
+ start();
+ }
};
// pop hide
const onContentHide = () => {
- restProps.onHide?.();
+ restProps.onOpenChange?.(false);
};
const updatePopup = () => {
@@ -131,7 +136,7 @@ const Tooltip = React.forwardRef((props, ref) => {
* it actively uninstalls events
*/
useEffect(() => {
- if (!open) {
+ if (!open && !stopWhenControlledOrDisabled()) {
stop?.();
}
}, [open]);
@@ -152,6 +157,8 @@ const Tooltip = React.forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
/** tooltip component */
tooltipRef,
+ /** 获取popup的ref */
+ popupRef: tooltipRef.current?.popupRef,
/** open Popup */
onOpen,
/** close Popup */
@@ -178,6 +185,8 @@ const Tooltip = React.forwardRef((props, ref) => {
{
updatePopup();
}}
@@ -185,7 +194,7 @@ const Tooltip = React.forwardRef((props, ref) => {
onMouseLeave={onMouseleave}
onClick={onClick}
>
- {children}
+ {TriggerNode}
((props, ref) => {
zIndex={restProps.zIndex}
transitionName={restProps.transitionName}
duration={restProps.duration}
- overlayClassName={classNames(restProps.overlayClassName, restProps.internalClassName || ns.b())}
+ overlayClassName={classNames(restProps.internalClassName || ns.b(), restProps.overlayClassName)}
overlayStyle={restProps.overlayStyle}
getPopupContainer={restProps.getPopupContainer}
onMouseEnter={onMouseenter}
diff --git a/packages/components/tooltip/trigger-type.ts b/packages/components/tooltip/trigger-type.ts
index af7711c..b6775ee 100644
--- a/packages/components/tooltip/trigger-type.ts
+++ b/packages/components/tooltip/trigger-type.ts
@@ -3,9 +3,14 @@
* @Description: Modify here please
*/
export interface ITooltipTriggerProps {
- children: React.ReactNode;
+ /** !!! This is a trigger node, which does not need to be passed because it can be passed after the virtual node */
+ children?: React.ReactNode;
/** trigger */
trigger?: "hover" | "click";
+ /** Used to identify whether virtual triggering is enabled */
+ virtualTriggering?: boolean;
+ /** Identify the triggering elements during virtual triggering */
+ virtualRef?: React.MutableRefObject;
onMouseEnter?: (e: any) => void;
onMouseLeave?: (e: any) => void;
onClick?: (e: any) => void;
diff --git a/packages/components/tooltip/trigger.tsx b/packages/components/tooltip/trigger.tsx
index b0d6263..2df54c7 100644
--- a/packages/components/tooltip/trigger.tsx
+++ b/packages/components/tooltip/trigger.tsx
@@ -2,7 +2,7 @@
* @Date: 2024-08-25 14:09:59
* @Description: Modify here please
*/
-import React, { useContext, cloneElement } from "react";
+import React, { useContext, cloneElement, useEffect } from "react";
import ResizeObserver from "rc-resize-observer";
import { TooltipContext } from "./utils";
import type { ITooltipTriggerProps } from "./trigger-type";
@@ -13,10 +13,12 @@ function isFragment(child: React.ReactNode): boolean {
}
const TooltipRigger: React.FC void; open: boolean }> = (props) => {
- const { children, open, onTargetResize, ...restProps } = props;
+ const { children, open, onTargetResize, virtualRef, virtualTriggering, ...restProps } = props;
const { triggerRef } = useContext(TooltipContext);
- const child = React.isValidElement(children) && !isFragment(children) ? children : {children};
+ const isExistNode = React.isValidElement(children);
+
+ const child = isExistNode && !isFragment(children) ? children : {children};
// Transfer props to cloneProps for use by the target node
const passedProps: Record = {};
@@ -31,15 +33,32 @@ const TooltipRigger: React.FC voi
});
// Child Node
- const triggerNode = cloneElement(child, {
- ...passedProps,
- ref: triggerRef
- });
+ const triggerNode = isExistNode
+ ? cloneElement(child, {
+ ...passedProps,
+ ref: triggerRef
+ })
+ : null;
+
+ /**
+ * Replace trigger, To achieve triggering of different virtual elements
+ * Unfortunately, it can only actively use “visible” outside to control Popup
+ */
+ useEffect(() => {
+ // replace trigger
+ if (virtualRef?.current && virtualTriggering) {
+ triggerRef.current = virtualRef?.current;
+ }
+ }, [virtualRef?.current, virtualTriggering]);
return (
-
- {triggerNode}
-
+ <>
+ {isExistNode ? (
+
+ {triggerNode}
+
+ ) : null}
+ >
);
};
diff --git a/packages/shared/use-click-away/index.ts b/packages/shared/use-click-away/index.ts
index 7ab33a6..e893f41 100644
--- a/packages/shared/use-click-away/index.ts
+++ b/packages/shared/use-click-away/index.ts
@@ -40,7 +40,6 @@ export function useClickAway(
if (!enable) {
return;
}
-
const handler = (event: any) => {
const targets = Array.isArray(target) ? target : [target];
if (
From 8b2f01e8f27a706ca713c3eb14dbff37924fb481 Mon Sep 17 00:00:00 2001
From: "PL196\\40380" <403802162@qq.com>
Date: Sun, 8 Sep 2024 19:53:49 +0800
Subject: [PATCH 3/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
packages/components/tooltip/composables/use-popup.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/components/tooltip/composables/use-popup.ts b/packages/components/tooltip/composables/use-popup.ts
index 70a5afc..c253bc0 100644
--- a/packages/components/tooltip/composables/use-popup.ts
+++ b/packages/components/tooltip/composables/use-popup.ts
@@ -19,7 +19,7 @@ import { useZIndex } from "@camelia/core/hooks";
import { TooltipContext } from "../utils";
import type { ITooltipPopupProps } from "../popup-type";
-export const usePopup = (props: ITooltipPopupProps) => {
+export const usePopup = (props: ITooltipPopupProps): any => {
const { open, disabled, zIndex, placement, strategy, offset, overlayStyle, showArrow } = props;
const { popupRef, triggerRef, role } = useContext(TooltipContext);