1
0
Эх сурвалжийг харах

feat: add keepDOM to portal component

代强 2 жил өмнө
parent
commit
2c96ecd82a

+ 25 - 24
content/show/popover/index-en-US.md

@@ -531,31 +531,32 @@ Please refer to [Use with Tooltip/Popconfirm](/en-US/show/tooltip#%E6%90%AD%E9%8
 
 ## API Reference
 
-| Properties | Instructions | Type | Default | Version |
-| --- | --- | --- | --- | --- |
-| autoAdjustOverflow | Whether to automatically adjust the expansion direction of the floating layer for automatic adjustment of the expansion direction during edge occlusion | boolean | true |
-| arrowPointAtCenter | Whether the "small triangle" points to the center of the element, you need to pass in "showArrow = true" at the same time | boolean | true | **0.34.0** |
-| closeOnEsc | Whether to close the panel by pressing the Esc key in the trigger or popup layer. It does not take effect when visible is under controlled | boolean | true | **2.8.0** |
-| content | Content displayed | string \| ReactNode |  |
-| clickToHide | Whether to automatically close the elastic layer when clicking on the floating layer and any element inside | boolean | false | **0.24.0** |
-| disableFocusListener | When trigger is `hover`, does not respond to the keyboard focus popup event, see details at [issue#977](https://github.com/DouyinFE/semi-design/issues/977) | boolean | true | **2.17.0** |
-| getPopupContainer | Specifies the parent DOM, and the bullet layer will be rendered to the DOM, you need to set 'position: relative` | () => HTMLElement | () => document.body |
-| guardFocus | When the focus is in the popup layer, toggle whether the Tab makes the focus loop in the popup layer | boolean | true | **2.8.0** |
+| Properties | Instructions                                                                                                                                                                                                                                  | Type | Default | Version |
+| --- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| --- | --- | --- |
+| autoAdjustOverflow | Whether to automatically adjust the expansion direction of the floating layer for automatic adjustment of the expansion direction during edge occlusion                                                                                       | boolean | true |
+| arrowPointAtCenter | Whether the "small triangle" points to the center of the element, you need to pass in "showArrow = true" at the same time                                                                                                                     | boolean | true | **0.34.0** |
+| closeOnEsc | Whether to close the panel by pressing the Esc key in the trigger or popup layer. It does not take effect when visible is under controlled                                                                                                    | boolean | true | **2.8.0** |
+| content | Content displayed                                                                                                                                                                                                                             | string \| ReactNode |  |
+| clickToHide | Whether to automatically close the elastic layer when clicking on the floating layer and any element inside                                                                                                                                   | boolean | false | **0.24.0** |
+| disableFocusListener | When trigger is `hover`, does not respond to the keyboard focus popup event, see details at [issue#977](https://github.com/DouyinFE/semi-design/issues/977)                                                                                   | boolean | true | **2.17.0** |
+| getPopupContainer | Specifies the parent DOM, and the bullet layer will be rendered to the DOM, you need to set 'position: relative`                                                                                                                              | () => HTMLElement | () => document.body |
+| guardFocus | When the focus is in the popup layer, toggle whether the Tab makes the focus loop in the popup layer                                                                                                                                          | boolean | true | **2.8.0** |
 | margin | Popup layer calculates the size of the safe area when the current direction overflows, used in scenes covered by fixed elements, more detail refer to [issue#549](https://github.com/DouyinFE/semi-design/issues/549), same as Tooltip margin | object\|number |  | 2.25.0 |
-| mouseEnterDelay | After the mouse is moved in, the display delay time, in milliseconds (only effective when the trigger is hover/focus) | number | 50 |  |
-| mouseLeaveDelay | The time for the delay to disappear after the mouse is moved out, in milliseconds (only effective when the trigger is hover/focus) | number | 50 |  |
-| rePosKey | You can update the value of this item to manually trigger the repositioning of the pop-up layer | string\|number |  |  |
-| returnFocusOnClose | After pressing the Esc key, whether the focus returns to the trigger, it only takes effect when the trigger is set to hover, focus, click, etc | boolean | true | **2.8.0** |
-| visible | Display popup or not | boolean |  |
-| position | Directions, optional values: `top`, `topLeft`, `topRight`, `left`, `leftTop`, `leftBottom`, `right`, `rightTop`, `rightBottom`, `bottom`, `bottomLeft`, `bottomRight` | string | "bottom" |
-| spacing | The distance between the out layer and the children element, in px | number | 4(while showArrow=false) 10(while showArrow=true) |  |
-| showArrow | Display little arrow or not | boolean |  |
-| trigger | Trigger mode, optional value: `hover`, `focus`, `click`, `custom` | string | 'hover' |
-| stopPropagation | Whether to prevent click events on the bomb layer from bubbling | boolean | false | **0.34.0** |
-| zIndex | Floating layer z-index value | number | 1030 |
-| onClickOutSide  | Callback when the pop-up layer is in the display state and the non-Children, non-floating layer inner area is clicked (only valid when trigger is custom, click) | (e:event) => void | | **2.1.0** |
-| onEscKeyDown | Called when Esc key is pressed in trigger or popup layer | function(e:event) | | **2.8.0** |
-| onVisibleChange | A callback triggered when the pop-up layer is displayed / hidden | (isVisible: boolean) => void |  |
+| mouseEnterDelay | After the mouse is moved in, the display delay time, in milliseconds (only effective when the trigger is hover/focus)                                                                                                                         | number | 50 |  |
+| mouseLeaveDelay | The time for the delay to disappear after the mouse is moved out, in milliseconds (only effective when the trigger is hover/focus)                                                                                                            | number | 50 |  |
+| rePosKey | You can update the value of this item to manually trigger the repositioning of the pop-up layer                                                                                                                                               | string\|number |  |  |
+| returnFocusOnClose | After pressing the Esc key, whether the focus returns to the trigger, it only takes effect when the trigger is set to hover, focus, click, etc                                                                                                | boolean | true | **2.8.0** |
+| visible | Display popup or not                                                                                                                                                                                                                          | boolean |  |
+| position | Directions, optional values: `top`, `topLeft`, `topRight`, `left`, `leftTop`, `leftBottom`, `right`, `rightTop`, `rightBottom`, `bottom`, `bottomLeft`, `bottomRight`                                                                         | string | "bottom" |
+| spacing | The distance between the out layer and the children element, in px                                                                                                                                                                            | number | 4(while showArrow=false) 10(while showArrow=true) |  |
+| showArrow | Display little arrow or not                                                                                                                                                                                                                   | boolean |  |
+| trigger | Trigger mode, optional value: `hover`, `focus`, `click`, `custom`                                                                                                                                                                             | string | 'hover' |
+| stopPropagation | Whether to prevent click events on the bomb layer from bubbling                                                                                                                                                                               | boolean | false | **0.34.0** |
+| zIndex | Floating layer z-index value                                                                                                                                                                                                                  | number | 1030 |
+| onClickOutSide  | Callback when the pop-up layer is in the display state and the non-Children, non-floating layer inner area is clicked (only valid when trigger is custom, click)                                                                              | (e:event) => void | | **2.1.0** |
+| onEscKeyDown | Called when Esc key is pressed in trigger or popup layer                                                                                                                                                                                      | function(e:event) | | **2.8.0** |
+| onVisibleChange | A callback triggered when the pop-up layer is displayed / hidden                                                                                                                                                                              | (isVisible: boolean) => void |  |
+| keepDOM | Whether to keep internal components from being destroyed when closing                                          | boolean | false | **2.31.0** |
 
 ## Accessibility
 

+ 11 - 10
content/show/popover/index.md

@@ -528,21 +528,21 @@ import { Button, Input, Popover, Space } from '@douyinfe/semi-ui';
 
 ## API 参考
 
-| 属性               | 说明                      | 类型                       | 默认值                                      | 版本       |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------- | ---------- |
+| 属性               | 说明                      | 类型                       | 默认值                                      | 版本         |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------- |------------|
 | autoAdjustOverflow | 是否自动调整弹出层展开方向,用于边缘遮挡时自动调整展开方向                                                                                  | boolean                    | true                                        |            |
 | arrowPointAtCenter | “小三角”是否指向元素中心,需要同时传入"showArrow=true"                                                                                      | boolean                    | true                                        | **0.34.0** |
-| closeOnEsc         | 在 trigger 或 弹出层按 Esc 键是否关闭面板,受控时不生效 | boolean | true | **2.8.0** |
-| content            | 显示的内容(函数类型,2.8.0 版本支持)                                                                                                                                  | ReactNode \| ({ initialFocusRef }) => ReactNode          |                                             |            |
+| closeOnEsc         | 在 trigger 或 弹出层按 Esc 键是否关闭面板,受控时不生效 | boolean | true | **2.8.0**  |
+| content            | 显示的内容(函数类型,2.8.0 版本支持)                                                                                                                                  | ReactNode \| ({ initialFocusRef }) => ReactNode          |            |            |
 | clickToHide        | 点击弹出层及内部任一元素时是否自动关闭弹层                                                                                                  | boolean                    | false                                       | **0.24.0** |
 | disableFocusListener | trigger为`hover`时,不响应键盘聚焦弹出浮层事件,详见[issue#977](https://github.com/DouyinFE/semi-design/issues/977) | boolean | true | **2.17.0** |
 | getPopupContainer  | 指定父级 DOM,弹层将会渲染至该 DOM 中,自定义需要设置 `position: relative`                                                                  | function():HTMLElement     | () => document.body                         |            |
-| guardFocus         | 当焦点处于弹出层内时,切换 Tab 是否让焦点在弹出层内循环 | boolean | true | **2.8.0** |
-| margin     |  弹出层计算溢出时的增加的冗余值,详见[issue#549](https://github.com/DouyinFE/semi-design/issues/549),作用同 Tooltip margin                        | number\|object                     |                                          |  **2.25.0**   |
+| guardFocus         | 当焦点处于弹出层内时,切换 Tab 是否让焦点在弹出层内循环 | boolean | true | **2.8.0**  |
+| margin     |  弹出层计算溢出时的增加的冗余值,详见[issue#549](https://github.com/DouyinFE/semi-design/issues/549),作用同 Tooltip margin                        | number\|object                     |            |  **2.25.0**   |
 | mouseEnterDelay    | 鼠标移入后,延迟显示的时间,单位毫秒(仅当 trigger 为 hover/focus 时生效)                                                                  | number                     | 50                                          |            |
 | mouseLeaveDelay    | 鼠标移出后,延迟消失的时间,单位毫秒(仅当 trigger 为 hover/focus 时生效)                                                                  | number                     | 50                                          |            |
-| rePosKey           | 可以更新该项值手动触发弹出层的重新定位                                                                                                         | string\|number             |                                            |             |
-| returnFocusOnClose | 按下 Esc 键后,焦点是否回到 trigger 上,设置 trigger 为 hover, focus, click 时生效 | boolean | true  | **2.8.0** |
+| rePosKey           | 可以更新该项值手动触发弹出层的重新定位                                                                                                         | string\|number             |            |             |
+| returnFocusOnClose | 按下 Esc 键后,焦点是否回到 trigger 上,设置 trigger 为 hover, focus, click 时生效 | boolean | true  | **2.8.0**  |
 | position           | 方向,可选值:`top`,`topLeft`,`topRight`,`left`,`leftTop`,`leftBottom`,`right`,`rightTop`,`rightBottom`,`bottom`,`bottomLeft`,`bottomRight` | string                     | "bottom"                                    |            |
 | spacing            | 弹出层与 children 元素的距离,单位 px                                                                                                       | number                     | 4(showArrow=false 时) 10(showArrow=true 时) |            |
 | showArrow          | 是否显示“小三角”                                                                                                                            | boolean                    |                                             |            |
@@ -550,9 +550,10 @@ import { Button, Input, Popover, Space } from '@douyinfe/semi-ui';
 | trigger            | 触发方式,可选值:`hover`, `focus`, `click`, `custom`                                                                                       | string                     | 'hover'                                     |            |
 | visible            | 是否显示,配合trigger='custom'可实现完全受控                                                                                                                                    | boolean                    |                                             |            |
 | zIndex             | 弹出层 z-index 值                                                                                                                             | number                     | 1030                                        |            |
-| onClickOutSide     | 当弹出层处于展示状态,点击非Children、非浮层内部区域时的回调(仅trigger为custom、click时有效)| function(e:event) |  | **2.1.0** |
-| onEscKeyDown       | 在 trigger 或 弹出层按 Esc 键时调用        | function(e:event) | | **2.8.0** |
+| onClickOutSide     | 当弹出层处于展示状态,点击非Children、非浮层内部区域时的回调(仅trigger为custom、click时有效)| function(e:event) |  | **2.1.0**  |
+| onEscKeyDown       | 在 trigger 或 弹出层按 Esc 键时调用        | function(e:event) | | **2.8.0**  |
 | onVisibleChange    | 弹出层展示/隐藏时触发的回调                                                                                                                 | function(isVisble:boolean) |                                             |            |
+| keepDOM | 关闭时是否保留内部组件不销毁 | boolean | false | **2.31.0** |
 
 ## Accessibility
 

+ 1 - 0
content/show/tooltip/index-en-US.md

@@ -359,6 +359,7 @@ import { Popconfirm, Tooltip, Button } from '@douyinfe/semi-ui';
 | zIndex              | Bullet levels.           | number                      | 1060                |            |
 | onVisibleChange     | A callback triggered when the pop-up layer is displayed/hidden                                                                                                                                                                               | (isVisible: boolean) => void |                     |            |
 | onClickOutSide      | Callback when the pop-up layer is in the display state and the non-Children, non-floating layer inner area is clicked (only valid when trigger is custom, click)                                                                             | (e:event) => void           |                     | **2.1.0** |
+| keepDOM | Whether to keep internal components from being destroyed when closing                                          | boolean | false | **2.31.0** |
 
 
 ## Accessibility

+ 1 - 0
content/show/tooltip/index.md

@@ -390,6 +390,7 @@ function Demo() {
 | zIndex | 弹层层级 | number | 1060 |  |
 | onVisibleChange | 弹出层展示/隐藏时触发的回调 | function(isVisible:boolean) |  |  |
 | onClickOutSide | 当弹出层处于展示状态,点击非Children、非浮层内部区域时的回调(仅trigger为custom、click时有效)| function(e:event) |  | **2.1.0** |
+| keepDOM | 关闭时是否保留内部组件不销毁 | boolean | false | **2.31.0** |
 
 ## Accessibility
 

+ 9 - 1
packages/semi-foundation/tooltip/foundation.ts

@@ -38,6 +38,7 @@ export interface TooltipAdapter<P = Record<string, any>, S = Record<string, any>
     unregisterScrollHandler(): void;
     insertPortal(...args: any[]): void;
     removePortal(...args: any[]): void;
+    setDisplayNone:(displayNone:boolean, cb?:()=>void)=>void;
     getEventName(): {
         mouseEnter: string;
         mouseLeave: string;
@@ -138,6 +139,10 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
         this._adapter.removePortal();
     }
 
+    setDisplayNone:(displayNone:boolean, cb?:()=>void)=>void = (displayNone, cb) => {
+        this._adapter.setDisplayNone(displayNone, cb);
+    }
+
     _adjustPos(position = '', isVertical = false, adjustType = 'reverse', concatPos?: any) {
         switch (adjustType) {
             case 'reverse':
@@ -294,7 +299,10 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
         const content = this.getProp('content');
         const trigger = this.getProp('trigger');
         const clickTriggerToHide = this.getProp('clickTriggerToHide');
-        const { visible } = this.getStates();
+        const { visible, displayNone } = this.getStates();
+        if (displayNone){
+            this.setDisplayNone(false);
+        }
         if (visible) {
             return ;
         }

+ 3 - 1
packages/semi-ui/popover/index.tsx

@@ -47,7 +47,9 @@ export interface PopoverProps extends BaseProps {
     onEscKeyDown?: TooltipProps['onEscKeyDown'];
     clickToHide?:TooltipProps['clickToHide'];
     disableFocusListener?: boolean;
-    afterClose?:()=>void
+    afterClose?:()=>void;
+
+    keepDOM?:boolean
 }
 
 export interface PopoverState {

+ 19 - 7
packages/semi-ui/tooltip/index.tsx

@@ -78,7 +78,8 @@ export interface TooltipProps extends BaseProps {
     wrapperId?: string;
     preventScroll?: boolean;
     disableFocusListener?: boolean;
-    afterClose?: () => void
+    afterClose?: () => void;
+    keepDOM?: boolean
 }
 interface TooltipState {
     visible: boolean;
@@ -94,7 +95,8 @@ interface TooltipState {
     placement: Position;
     transitionStyle: Record<string, any>;
     isPositionUpdated: boolean;
-    id: string
+    id: string;
+    displayNone:boolean
 }
 
 const prefix = cssClasses.PREFIX;
@@ -141,6 +143,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
         guardFocus: PropTypes.bool,
         returnFocusOnClose: PropTypes.bool,
         preventScroll: PropTypes.bool,
+        keepDOM: PropTypes.bool,
     };
 
     static defaultProps = {
@@ -168,6 +171,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
         onEscKeyDown: noop,
         disableFocusListener: false,
         disableArrowKeyDown: false,
+        keepDOM: false
     };
 
     eventManager: Event;
@@ -202,7 +206,8 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
             placement: props.position || 'top',
             transitionStyle: {},
             isPositionUpdated: false,
-            id: props.wrapperId, // auto generate id, will be used by children.aria-describedby & content.id, improve a11y
+            id: props.wrapperId, // auto generate id, will be used by children.aria-describedby & content.id, improve a11y,
+            displayNone: false
         };
         this.foundation = new TooltipFoundation(this.adapter);
         this.eventManager = new Event();
@@ -314,6 +319,9 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
                     }
                 );
             },
+            setDisplayNone: (displayNone:boolean, cb:()=>void)=>{
+                this.setState({ displayNone }, cb);
+            },
             updatePlacementAttr: (placement: Position) => {
                 this.setState({ placement });
             },
@@ -488,7 +496,11 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
     // };
 
     didLeave = () => {
-        this.foundation.removePortal();
+        if (this.props.keepDOM){
+            this.foundation.setDisplayNone(true);
+        } else {
+            this.foundation.removePortal();
+        }
         this.foundation.unBindEvent();
     };
     /** for transition - end */
@@ -562,7 +574,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
     };
 
     renderPortal = () => {
-        const { containerStyle = {}, visible, portalEventSet, placement, transitionState, id, isPositionUpdated } = this.state;
+        const { containerStyle = {}, visible, portalEventSet, placement, displayNone, transitionState, id, isPositionUpdated } = this.state;
         const { prefixCls, content, showArrow, style, motion, role, zIndex } = this.props;
         const contentNode = this.renderContentNode(content);
         const { className: propClassName } = this.props;
@@ -578,7 +590,6 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
         const transformOrigin = get(containerStyle, 'transformOrigin');
         const userOpacity = get(style, 'opacity');
         const opacity = userOpacity ? userOpacity : 1;
-
         const inner =
             <CSSAnimation
                 fillMode="forwards"
@@ -597,10 +608,11 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
                             className={classNames(className, animationClassName)}
                             style={{
                                 ...animationStyle,
+                                display: displayNone ? 'none' : 'block',
                                 transformOrigin,
                                 ...style,
                                 opacity: isPositionUpdated ? opacity : "0",
-                            }}
+                            }} 
                             {...portalEventSet}
                             {...animationEventsNeedBind}
                             role={role}