diff --git a/.fatherrc.js b/.fatherrc.js index 912aa0aa..4ddbafd1 100644 --- a/.fatherrc.js +++ b/.fatherrc.js @@ -1,9 +1,5 @@ -export default { - cjs: 'babel', - esm: { type: 'babel', importLibToEs: true }, - preCommit: { - eslint: true, - prettier: true, - }, - runtimeHelpers: true, -}; +import { defineConfig } from 'father'; + +export default defineConfig({ + plugins: ['@rc-component/father-plugin'], +}); \ No newline at end of file diff --git a/assets/bootstrap_white.less b/assets/bootstrap_white.less index 07b47858..b6deb247 100644 --- a/assets/bootstrap_white.less +++ b/assets/bootstrap_white.less @@ -69,7 +69,8 @@ &-placement-top &-arrow, &-placement-topLeft &-arrow, &-placement-topRight &-arrow{ - bottom: -@tooltip-arrow-width + @tooltip-shadow-width; + // bottom: -@tooltip-arrow-width + @tooltip-shadow-width; + transform: translate(-50%, @tooltip-arrow-width - @tooltip-shadow-width); margin-left: -@tooltip-arrow-width; border-width: @tooltip-arrow-width @tooltip-arrow-width 0; border-top-color: @tooltip-arrow-color; @@ -161,7 +162,8 @@ &-placement-bottom &-arrow, &-placement-bottomLeft &-arrow, &-placement-bottomRight &-arrow { - top: -@tooltip-arrow-width + @tooltip-shadow-width;; + // top: -@tooltip-arrow-width + @tooltip-shadow-width;; + transform: translate(-50%, -@tooltip-arrow-width + @tooltip-shadow-width); margin-left: -@tooltip-arrow-width; border-width: 0 @tooltip-arrow-width @tooltip-arrow-width; border-bottom-color: @tooltip-arrow-color; diff --git a/docs/demo/point.md b/docs/demo/point.md new file mode 100644 index 00000000..073a89bc --- /dev/null +++ b/docs/demo/point.md @@ -0,0 +1,8 @@ +--- +title: Point +nav: + title: Demo + path: /demo +--- + + \ No newline at end of file diff --git a/docs/examples/point.tsx b/docs/examples/point.tsx new file mode 100644 index 00000000..d59ce6a2 --- /dev/null +++ b/docs/examples/point.tsx @@ -0,0 +1,56 @@ +import Tooltip from 'rc-tooltip'; +import React from 'react'; +import '../../assets/bootstrap_white.less'; + +const text = Tooltip Text; + +const Test = () => { + const scrollRef = React.useRef(); + + return ( +
+
+
+ } + > +
+ Hover Me +
+
+
+
+
+ ); +}; + +export default Test; diff --git a/package.json b/package.json index 751f33c9..c452f86a 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,11 @@ "url": "git@github.com:react-component/tooltip.git" }, "license": "MIT", + "maintainers": [ + "yiminghe@gmail.com" + ], + "main": "lib/index", + "module": "es/index", "files": [ "dist", "lib", @@ -24,25 +29,23 @@ "assets/*.css", "assets/*.less" ], - "main": "lib/index", - "module": "es/index", "scripts": { - "start": "dumi dev", + "compile": "father build && lessc assets/bootstrap.less assets/bootstrap.css && lessc assets/bootstrap_white.less assets/bootstrap_white.css", "docs:build": "dumi build", "docs:deploy": "gh-pages -d .doc", - "compile": "father build && lessc assets/bootstrap.less assets/bootstrap.css && lessc assets/bootstrap_white.less assets/bootstrap_white.css", - "coverage": "father test --coverage", "lint": "eslint src/ --ext .tsx,.ts,.jsx,.js", "now-build": "npm run build", "prepublishOnly": "npm run compile && np --no-cleanup --yolo --no-publish", - "test": "father test" + "start": "dumi dev", + "test": "rc-test" }, "dependencies": { "@babel/runtime": "^7.11.2", - "classnames": "^2.3.1", - "rc-trigger": "^5.3.1" + "@rc-component/trigger": "^1.0.4", + "classnames": "^2.3.1" }, "devDependencies": { + "@rc-component/father-plugin": "^1.0.0", "@testing-library/react": "^13.4.0", "@types/jest": "^26.0.0", "@types/react": "^18.0.26", @@ -51,18 +54,15 @@ "cross-env": "^7.0.0", "dumi": "^2.1.1", "eslint": "^7.1.0", - "father": "^2.23.1", - "father-build": "^1.18.6", + "father": "^4.0.0", "gh-pages": "^3.1.0", "less": "^3.11.1", "np": "^7.1.0", + "rc-test": "^7.0.9", "react": "^18.2.0", "react-dom": "^18.2.0", "typescript": "^4.0.5" }, - "maintainers": [ - "yiminghe@gmail.com" - ], "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" diff --git a/src/Popup.tsx b/src/Popup.tsx index 6357e7bd..cbaa9cf3 100644 --- a/src/Popup.tsx +++ b/src/Popup.tsx @@ -1,36 +1,20 @@ -import * as React from 'react'; import classNames from 'classnames'; +import * as React from 'react'; export interface ContentProps { prefixCls?: string; children: (() => React.ReactNode) | React.ReactNode; id?: string; overlayInnerStyle?: React.CSSProperties; - arrowContent?: React.ReactNode; className?: string; style?: React.CSSProperties; - showArrow?: boolean; } export default function Popup(props: ContentProps) { - const { - showArrow, - arrowContent, - children, - prefixCls, - id, - overlayInnerStyle, - className, - style, - } = props; + const { children, prefixCls, id, overlayInnerStyle, className, style } = props; return (
- {showArrow !== false && ( -
- {arrowContent} -
- )} diff --git a/src/Tooltip.tsx b/src/Tooltip.tsx index c703e353..bb836d3e 100644 --- a/src/Tooltip.tsx +++ b/src/Tooltip.tsx @@ -1,8 +1,8 @@ +import type { TriggerProps } from '@rc-component/trigger'; +import Trigger from '@rc-component/trigger'; +import type { ActionType, AlignType, AnimationType } from '@rc-component/trigger/lib/interface'; import * as React from 'react'; -import { useRef, useImperativeHandle, forwardRef } from 'react'; -import Trigger from 'rc-trigger'; -import type { TriggerProps } from 'rc-trigger'; -import type { AlignType, AnimationType, ActionType } from 'rc-trigger/lib/interface'; +import { forwardRef, useImperativeHandle, useRef } from 'react'; import { placements } from './placements'; import Popup from './Popup'; @@ -26,11 +26,7 @@ export interface TooltipProps extends Pick HTMLElement; - destroyTooltipOnHide?: - | boolean - | { - keepParent?: boolean; - }; + destroyTooltipOnHide?: boolean; align?: AlignType; showArrow?: boolean; arrowContent?: React.ReactNode; @@ -77,28 +73,11 @@ const Tooltip = (props: TooltipProps, ref) => { } const getPopupElement = () => ( - + {overlay} ); - let destroyTooltip = false; - let autoDestroy = false; - if (typeof destroyTooltipOnHide === 'boolean') { - destroyTooltip = destroyTooltipOnHide; - } else if (destroyTooltipOnHide && typeof destroyTooltipOnHide === 'object') { - const { keepParent } = destroyTooltipOnHide; - destroyTooltip = keepParent === true; - autoDestroy = keepParent === false; - } - return ( { popupAnimation={animation} popupMotion={motion} defaultPopupVisible={defaultVisible} - destroyPopupOnHide={destroyTooltip} - autoDestroy={autoDestroy} + autoDestroy={destroyTooltipOnHide} mouseLeaveDelay={mouseLeaveDelay} popupStyle={overlayStyle} mouseEnterDelay={mouseEnterDelay} + arrow={showArrow} {...extraProps} > {children} diff --git a/src/placements.tsx b/src/placements.tsx index 789dce36..6371e889 100644 --- a/src/placements.tsx +++ b/src/placements.tsx @@ -1,82 +1,84 @@ -import { BuildInPlacements } from 'rc-trigger'; +import type { BuildInPlacements } from '@rc-component/trigger'; -const autoAdjustOverflow = { - adjustX: 1, +const autoAdjustOverflowTopBottom = { + shiftX: 64, adjustY: 1, }; +const autoAdjustOverflowLeftRight = { adjustX: 1, shiftY: true }; + const targetOffset = [0, 0]; export const placements: BuildInPlacements = { left: { points: ['cr', 'cl'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowLeftRight, offset: [-4, 0], targetOffset, }, right: { points: ['cl', 'cr'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowLeftRight, offset: [4, 0], targetOffset, }, top: { points: ['bc', 'tc'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowTopBottom, offset: [0, -4], targetOffset, }, bottom: { points: ['tc', 'bc'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowTopBottom, offset: [0, 4], targetOffset, }, topLeft: { points: ['bl', 'tl'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowTopBottom, offset: [0, -4], targetOffset, }, leftTop: { points: ['tr', 'tl'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowLeftRight, offset: [-4, 0], targetOffset, }, topRight: { points: ['br', 'tr'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowTopBottom, offset: [0, -4], targetOffset, }, rightTop: { points: ['tl', 'tr'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowLeftRight, offset: [4, 0], targetOffset, }, bottomRight: { points: ['tr', 'br'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowTopBottom, offset: [0, 4], targetOffset, }, rightBottom: { points: ['bl', 'br'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowLeftRight, offset: [4, 0], targetOffset, }, bottomLeft: { points: ['tl', 'bl'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowTopBottom, offset: [0, 4], targetOffset, }, leftBottom: { points: ['br', 'bl'], - overflow: autoAdjustOverflow, + overflow: autoAdjustOverflowLeftRight, offset: [-4, 0], targetOffset, }, diff --git a/tests/__mocks__/@rc-component/trigger.js b/tests/__mocks__/@rc-component/trigger.js new file mode 100644 index 00000000..887c966d --- /dev/null +++ b/tests/__mocks__/@rc-component/trigger.js @@ -0,0 +1,3 @@ +import Trigger from '@rc-component/trigger/lib/mock'; + +export default Trigger; diff --git a/tests/__mocks__/rc-trigger.js b/tests/__mocks__/rc-trigger.js deleted file mode 100644 index 32303075..00000000 --- a/tests/__mocks__/rc-trigger.js +++ /dev/null @@ -1,3 +0,0 @@ -import Trigger from 'rc-trigger/lib/mock'; - -export default Trigger; diff --git a/tests/index.test.tsx b/tests/index.test.tsx index 2a9fc44e..6784be1a 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -1,5 +1,5 @@ -import React, { useState } from 'react'; -import { render, fireEvent } from '@testing-library/react'; +import { act, fireEvent, render } from '@testing-library/react'; +import React from 'react'; import Tooltip from '../src'; const verifyContent = (wrapper: HTMLElement, content: string) => { @@ -19,6 +19,15 @@ describe('rc-tooltip', () => { jest.useRealTimers(); }); + async function waitFakeTimers() { + for (let i = 0; i < 100; i += 1) { + await act(async () => { + jest.advanceTimersByTime(100); + await Promise.resolve(); + }); + } + } + describe('shows and hides itself on click', () => { it('using an element overlay', () => { const { container } = render( @@ -30,7 +39,9 @@ describe('rc-tooltip', () => {
Click this
, ); + fireEvent.click(container.querySelector('.target')); + verifyContent(container, 'Tooltip content'); }); @@ -81,11 +92,16 @@ describe('rc-tooltip', () => { expect(domRef.current).toBeTruthy(); }); }); + describe('destroyTooltipOnHide', () => { - const destroyVerifyContent = (wrapper: HTMLElement, content: string) => { + const destroyVerifyContent = async (wrapper: HTMLElement, content: string) => { fireEvent.click(wrapper.querySelector('.target')); + await waitFakeTimers(); + expect(wrapper.querySelector('.x-content').textContent).toBe(content); + fireEvent.click(wrapper.querySelector('.target')); + await waitFakeTimers(); }; it('default value', () => { const { container } = render( @@ -100,7 +116,8 @@ describe('rc-tooltip', () => { fireEvent.click(container.querySelector('.target')); verifyContent(container, 'Tooltip content'); }); - it('should only remove tooltip when value is true', () => { + + it('should only remove tooltip when value is true', async () => { const { container } = render( {
Click this
, ); - destroyVerifyContent(container, 'Tooltip content'); - expect(container.innerHTML).toBe('
Click this
'); - }); - it('should only remove tooltip when keepParent is true', () => { - const { container } = render( - Tooltip content} - > -
Click this
-
, - ); - destroyVerifyContent(container, 'Tooltip content'); - expect(container.innerHTML).toBe('
Click this
'); - }); - it('should remove tooltip and container when keepParent is false', () => { - const { container } = render( - Tooltip content} - > -
Click this
-
, - ); - destroyVerifyContent(container, 'Tooltip content'); - expect(container.innerHTML).toBe('
Click this
'); + await destroyVerifyContent(container, 'Tooltip content'); + expect(document.querySelector('.x-content')).toBeFalsy(); }); }); @@ -165,7 +154,7 @@ describe('rc-tooltip', () => { it('should show tooltip arrow default', () => { const { container } = render( Tooltip content} @@ -174,14 +163,12 @@ describe('rc-tooltip', () => { , ); fireEvent.click(container.querySelector('.target')); - expect(container.querySelector('.rc-tooltip-content').outerHTML).toBe( - '
', - ); + expect(container.querySelector('.rc-tooltip-arrow')).toBeTruthy(); }); it('should show tooltip arrow when showArrow is true', () => { const { container } = render( Tooltip content} @@ -191,14 +178,13 @@ describe('rc-tooltip', () => { , ); fireEvent.click(container.querySelector('.target')); - expect(container.querySelector('.rc-tooltip-content').outerHTML).toBe( - '
', - ); + console.log(container.innerHTML); + expect(container.querySelector('.rc-tooltip-arrow')).toBeTruthy(); }); it('should hide tooltip arrow when showArrow is false', () => { const { container } = render( Tooltip content} @@ -211,15 +197,13 @@ describe('rc-tooltip', () => { expect(container.querySelector('.rc-tooltip').classList).not.toContain( 'rc-tooltip-show-arrow', ); - expect(container.querySelector('.rc-tooltip-content').outerHTML).toBe( - '
', - ); + expect(container.querySelector('.rc-tooltip-arrow')).toBeFalsy(); }); }); it('visible', () => { const App = () => { - const [open, setOpen] = useState(false); + const [open, setOpen] = React.useState(false); return ( Tooltip content} visible={open}>