From 7634a74f830e53f159c9a9f93108d04a6f78e026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Mon, 20 Mar 2023 10:26:08 +0800 Subject: [PATCH 001/118] chore: fix React 18.3 warning (#732) --- package.json | 4 ++-- src/TreeNode.tsx | 8 ++++---- tests/React18.spec.tsx | 22 +++++++++++++++++++++- tests/util.spec.js | 11 +++++------ 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index f2c1d2e6f..5f07c8d08 100644 --- a/package.json +++ b/package.json @@ -70,8 +70,8 @@ "rc-dialog": "^8.1.0", "rc-tooltip": "5.x", "rc-trigger": "^5.0.7", - "react": "^18.0.0", - "react-dom": "^18.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", "typescript": "^4.0.2" }, "dependencies": { diff --git a/src/TreeNode.tsx b/src/TreeNode.tsx index c3c76faf5..d8b5129ef 100644 --- a/src/TreeNode.tsx +++ b/src/TreeNode.tsx @@ -438,7 +438,7 @@ class InternalTreeNode extends React.Component { const { dragNodeHighlight } = this.state; - const { title, selected, icon, loading, data } = this.props; + const { title = defaultTitle, selected, icon, loading, data } = this.props; const { context: { prefixCls, showIcon, icon: treeIcon, loadData, titleRender }, } = this.props; @@ -620,9 +620,9 @@ const ContextTreeNode: React.FC = props => ( ContextTreeNode.displayName = 'TreeNode'; -ContextTreeNode.defaultProps = { - title: defaultTitle, -}; +// ContextTreeNode.defaultProps = { +// title: defaultTitle, +// }; (ContextTreeNode as any).isTreeNode = 1; diff --git a/tests/React18.spec.tsx b/tests/React18.spec.tsx index 0e945d9df..2db0146da 100644 --- a/tests/React18.spec.tsx +++ b/tests/React18.spec.tsx @@ -1,8 +1,28 @@ +import { fireEvent, render } from '@testing-library/react'; import React from 'react'; -import { render, fireEvent } from '@testing-library/react'; import Tree from '../src'; describe('React 18', () => { + // This does not real work since waring is in 18.3.0 but current still is next version. + it('no warning', () => { + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + render( + + + , + ); + + expect(errSpy).not.toHaveBeenCalled(); + }); + it('expand work', () => { const onExpand = jest.fn(); const { container } = render( diff --git a/tests/util.spec.js b/tests/util.spec.js index 072bd965b..a0b735301 100644 --- a/tests/util.spec.js +++ b/tests/util.spec.js @@ -1,22 +1,21 @@ /* eslint-disable no-undef, react/no-multi-comp, react/no-unused-state, react/prop-types, no-return-assign */ -import React from 'react'; import Tree, { TreeNode } from '../src'; import { - convertDataToTree, conductExpandParent, + convertDataToTree, getDragChildrenKeys, parseCheckedKeys, } from '../src/util'; +import { conductCheck } from '../src/utils/conductUtil'; import { - flattenTreeData, - convertTreeToData, convertDataToEntities, + convertTreeToData, + flattenTreeData, getTreeNodeProps, traverseDataNodes, } from '../src/utils/treeUtil'; import { spyConsole, spyError } from './util'; -import { conductCheck } from '../src/utils/conductUtil'; describe('Util', () => { spyConsole(); @@ -58,7 +57,7 @@ describe('Util', () => { }, ], }, - { key: '!', title: '---', really: true }, + { key: '!', really: true }, ]); }); From d8b6e2d876526c41977241805cd9a4c49fb2a12d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Mon, 20 Mar 2023 10:34:05 +0800 Subject: [PATCH 002/118] chore: clean up (#733) --- src/TreeNode.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/TreeNode.tsx b/src/TreeNode.tsx index d8b5129ef..a32b12b42 100644 --- a/src/TreeNode.tsx +++ b/src/TreeNode.tsx @@ -620,10 +620,6 @@ const ContextTreeNode: React.FC = props => ( ContextTreeNode.displayName = 'TreeNode'; -// ContextTreeNode.defaultProps = { -// title: defaultTitle, -// }; - (ContextTreeNode as any).isTreeNode = 1; export { InternalTreeNode }; From 4c9cc52a62f7187b8507d0eadee2a47d571832eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Mon, 20 Mar 2023 10:36:48 +0800 Subject: [PATCH 003/118] 5.7.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5f07c8d08..bd7c112b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-tree", - "version": "5.7.2", + "version": "5.7.3", "description": "tree ui component for react", "engines": { "node": ">=10.x" From 660e325c51d973c405b70555cdc516b8f5dc53ee Mon Sep 17 00:00:00 2001 From: acyza <101238421+acyza@users.noreply.github.com> Date: Thu, 30 Mar 2023 23:32:13 +0800 Subject: [PATCH 004/118] fix: invalid animation (#735) * fix: invalid animation * chore: fix test * chore: fix test --- src/MotionTreeNode.tsx | 10 ++++++++-- tests/TreeMotion.spec.tsx | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/MotionTreeNode.tsx b/src/MotionTreeNode.tsx index d8cb6717c..0fd4b3786 100644 --- a/src/MotionTreeNode.tsx +++ b/src/MotionTreeNode.tsx @@ -51,15 +51,21 @@ const MotionTreeNode: React.ForwardRefRenderFunction { // Trigger motion only when patched if (motionNodes) { - onOriginMotionStart(); + if (reruningEffectFlag === null) { + onOriginMotionStart(); + } else { + clearTimeout(reruningEffectFlag); + } } return () => { if (motionNodes) { - onMotionEnd(); + reruningEffectFlag = setTimeout(onMotionEnd, 0); } }; }, []); diff --git a/tests/TreeMotion.spec.tsx b/tests/TreeMotion.spec.tsx index 187bc1988..496f1fb41 100644 --- a/tests/TreeMotion.spec.tsx +++ b/tests/TreeMotion.spec.tsx @@ -137,6 +137,9 @@ describe('Tree Motion', () => { expect(onMotionEnd).not.toHaveBeenCalled(); unmount(); + act(() => { + jest.runAllTimers(); + }); expect(onMotionEnd).toHaveBeenCalled(); }); @@ -166,6 +169,9 @@ describe('Tree Motion', () => { expect(onMotionEnd).not.toHaveBeenCalled(); unmount(); + act(() => { + jest.runAllTimers(); + }); expect(onMotionStart).not.toHaveBeenCalled(); expect(onMotionEnd).not.toHaveBeenCalled(); }); From a72fa8409586b1cba4e41f0fad2ca1ec549ace42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B4=8B?= <94534613+BoyYangzai@users.noreply.github.com> Date: Wed, 17 May 2023 21:27:41 +0800 Subject: [PATCH 005/118] chore: update virtual-list 5.3.1 (#744) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bd7c112b3..462c18a9c 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,6 @@ "classnames": "2.x", "rc-motion": "^2.0.1", "rc-util": "^5.16.1", - "rc-virtual-list": "^3.4.8" + "rc-virtual-list": "^3.5.1" } } From c69f16e2d1e690d26bfb62c72f328c0cec3f87cb Mon Sep 17 00:00:00 2001 From: yangxiuxiu <79584569+RicardoErii@users.noreply.github.com> Date: Wed, 24 May 2023 15:59:46 +0800 Subject: [PATCH 006/118] fix: TreeNode false flicker in re-render (#743) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: TreeNode false flicker in re-render * chore: adjust using rc-util --------- Co-authored-by: RicardoErii <‘1974364190@qq.com’> Co-authored-by: 二货机器人 --- src/NodeList.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/NodeList.tsx b/src/NodeList.tsx index 525bfd478..6bf73eb00 100644 --- a/src/NodeList.tsx +++ b/src/NodeList.tsx @@ -2,12 +2,13 @@ * Handle virtual list of the TreeNodes. */ -import * as React from 'react'; +import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect'; import VirtualList, { ListRef } from 'rc-virtual-list'; -import { BasicDataNode, FlattenNode, Key, DataEntity, DataNode, ScrollTo } from './interface'; +import * as React from 'react'; +import { BasicDataNode, DataEntity, DataNode, FlattenNode, Key, ScrollTo } from './interface'; import MotionTreeNode from './MotionTreeNode'; import { findExpandedKeys, getExpandRange } from './utils/diffUtil'; -import { getTreeNodeProps, getKey } from './utils/treeUtil'; +import { getKey, getTreeNodeProps } from './utils/treeUtil'; const HIDDEN_STYLE = { width: 0, @@ -199,7 +200,8 @@ const NodeList = React.forwardRef>((props, ref) } // Do animation if expanded keys changed - React.useEffect(() => { + // layoutEffect here to avoid blink of node removing + useLayoutEffect(() => { setPrevExpandedKeys(expandedKeys); const diffExpanded = findExpandedKeys(prevExpandedKeys, expandedKeys); From 33ccbeaca39f1a34c4a79597a7cd9ea52b4086ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 24 May 2023 16:10:30 +0800 Subject: [PATCH 007/118] 5.7.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 462c18a9c..85d6f3775 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-tree", - "version": "5.7.3", + "version": "5.7.4", "description": "tree ui component for react", "engines": { "node": ">=10.x" From 57511c8e8771cff71d47382362a4807487ba111f Mon Sep 17 00:00:00 2001 From: muxin Date: Wed, 14 Jun 2023 10:43:36 +0800 Subject: [PATCH 008/118] refactor: solve circule dependency (#749) * refactor: solve circule dependency * fix: add extra export path --- src/MotionTreeNode.tsx | 4 ++-- src/TreeNode.tsx | 40 ++-------------------------------------- src/index.ts | 3 +-- src/interface.tsx | 38 +++++++++++++++++++++++++++++++++++++- src/util.tsx | 10 ++-------- src/utils/treeUtil.ts | 27 +++++++++++++++++---------- 6 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/MotionTreeNode.tsx b/src/MotionTreeNode.tsx index 0fd4b3786..60d171693 100644 --- a/src/MotionTreeNode.tsx +++ b/src/MotionTreeNode.tsx @@ -2,8 +2,8 @@ import * as React from 'react'; import { useEffect } from 'react'; import classNames from 'classnames'; import CSSMotion from 'rc-motion'; -import TreeNode, { TreeNodeProps } from './TreeNode'; -import { FlattenNode } from './interface'; +import TreeNode from './TreeNode'; +import { FlattenNode, TreeNodeProps } from './interface'; import { getTreeNodeProps, TreeNodeRequiredProps } from './utils/treeUtil'; import { TreeContext } from './contextTypes'; diff --git a/src/TreeNode.tsx b/src/TreeNode.tsx index a32b12b42..dc4a319b4 100644 --- a/src/TreeNode.tsx +++ b/src/TreeNode.tsx @@ -3,7 +3,7 @@ import classNames from 'classnames'; import pickAttrs from 'rc-util/lib/pickAttrs'; // @ts-ignore import { TreeContext, TreeContextProps } from './contextTypes'; -import { IconType, Key, DataNode, BasicDataNode } from './interface'; +import { TreeNodeProps } from './interface'; import Indent from './Indent'; import { convertNodePropsToEventData } from './utils/treeUtil'; @@ -12,43 +12,7 @@ const ICON_CLOSE = 'close'; const defaultTitle = '---'; -export interface TreeNodeProps { - eventKey?: Key; // Pass by parent `cloneElement` - prefixCls?: string; - className?: string; - style?: React.CSSProperties; - id?: string; - - // By parent - expanded?: boolean; - selected?: boolean; - checked?: boolean; - loaded?: boolean; - loading?: boolean; - halfChecked?: boolean; - title?: React.ReactNode | ((data: TreeDataType) => React.ReactNode); - dragOver?: boolean; - dragOverGapTop?: boolean; - dragOverGapBottom?: boolean; - pos?: string; - domRef?: React.Ref; - /** New added in Tree for easy data access */ - data?: TreeDataType; - isStart?: boolean[]; - isEnd?: boolean[]; - active?: boolean; - onMouseMove?: React.MouseEventHandler; - - // By user - isLeaf?: boolean; - checkable?: boolean; - selectable?: boolean; - disabled?: boolean; - disableCheckbox?: boolean; - icon?: IconType; - switcherIcon?: IconType; - children?: React.ReactNode; -} +export type { TreeNodeProps } from './interface'; export interface InternalTreeNodeProps extends TreeNodeProps { context?: TreeContextProps; diff --git a/src/index.ts b/src/index.ts index e3ad61abb..57929b517 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,7 @@ import Tree from './Tree'; import TreeNode from './TreeNode'; import type { TreeProps } from './Tree'; -import type { TreeNodeProps } from './TreeNode'; -import type { BasicDataNode, FieldDataNode } from './interface'; +import type { TreeNodeProps, BasicDataNode, FieldDataNode } from './interface'; export { TreeNode }; export type { TreeProps, TreeNodeProps, BasicDataNode, FieldDataNode }; diff --git a/src/interface.tsx b/src/interface.tsx index bf45a2729..586cac3c6 100644 --- a/src/interface.tsx +++ b/src/interface.tsx @@ -1,7 +1,43 @@ import * as React from 'react'; -import { TreeNodeProps } from './TreeNode'; export { ScrollTo } from 'rc-virtual-list/lib/List'; +export interface TreeNodeProps { + eventKey?: Key; // Pass by parent `cloneElement` + prefixCls?: string; + className?: string; + style?: React.CSSProperties; + id?: string; + + // By parent + expanded?: boolean; + selected?: boolean; + checked?: boolean; + loaded?: boolean; + loading?: boolean; + halfChecked?: boolean; + title?: React.ReactNode | ((data: TreeDataType) => React.ReactNode); + dragOver?: boolean; + dragOverGapTop?: boolean; + dragOverGapBottom?: boolean; + pos?: string; + domRef?: React.Ref; + /** New added in Tree for easy data access */ + data?: TreeDataType; + isStart?: boolean[]; + isEnd?: boolean[]; + active?: boolean; + onMouseMove?: React.MouseEventHandler; + + // By user + isLeaf?: boolean; + checkable?: boolean; + selectable?: boolean; + disabled?: boolean; + disableCheckbox?: boolean; + icon?: IconType; + switcherIcon?: IconType; + children?: React.ReactNode; +} /** For fieldNames, we provides a abstract interface */ export interface BasicDataNode { diff --git a/src/util.tsx b/src/util.tsx index 6165bf463..6b8b1ef26 100644 --- a/src/util.tsx +++ b/src/util.tsx @@ -18,6 +18,8 @@ import { } from './interface'; import { TreeProps, AllowDrop } from './Tree'; +export { getPosition, isTreeNode } from './utils/treeUtil'; + export function arrDel(list: Key[], value: Key) { if (!list) return []; const clone = list.slice(); @@ -40,14 +42,6 @@ export function posToArr(pos: string) { return pos.split('-'); } -export function getPosition(level: string | number, index: number) { - return `${level}-${index}`; -} - -export function isTreeNode(node: NodeElement) { - return node && node.type && node.type.isTreeNode; -} - export function getDragChildrenKeys( dragNodeKey: Key, keyEntities: Record>, diff --git a/src/utils/treeUtil.ts b/src/utils/treeUtil.ts index 50a3f6375..5ea0b6cfb 100644 --- a/src/utils/treeUtil.ts +++ b/src/utils/treeUtil.ts @@ -1,20 +1,27 @@ -import * as React from 'react'; -import omit from 'rc-util/lib/omit'; import toArray from 'rc-util/lib/Children/toArray'; +import omit from 'rc-util/lib/omit'; import warning from 'rc-util/lib/warning'; +import * as React from 'react'; import { - DataNode, - FlattenNode, - NodeElement, + BasicDataNode, DataEntity, - Key, + DataNode, EventDataNode, - GetKey, FieldNames, - BasicDataNode, + FlattenNode, + GetKey, + Key, + NodeElement, + TreeNodeProps, } from '../interface'; -import { getPosition, isTreeNode } from '../util'; -import { TreeNodeProps } from '../TreeNode'; + +export function getPosition(level: string | number, index: number) { + return `${level}-${index}`; +} + +export function isTreeNode(node: NodeElement) { + return node && node.type && node.type.isTreeNode; +} export function getKey(key: Key, pos: string) { if (key !== null && key !== undefined) { From bf421a3e7d03d413ed8d1b69c56346a503366c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 14 Jun 2023 10:47:22 +0800 Subject: [PATCH 009/118] 5.7.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 85d6f3775..4c3eeda43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-tree", - "version": "5.7.4", + "version": "5.7.5", "description": "tree ui component for react", "engines": { "node": ">=10.x" From ed153ad66f612079f1e79ede11d36985c03b6468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Fri, 16 Jun 2023 11:21:48 +0800 Subject: [PATCH 010/118] fix: disabled motion will never end (#754) * refactor: use rc-util hooks * fix: motion of rc-motion * chore: patch onMotion * fix: adjust logic --- docs/examples/animation.jsx | 76 ++++++++++++++++++++++--------------- src/MotionTreeNode.tsx | 63 +++++++++++++++--------------- src/useUnmount.ts | 21 ++++++++++ tests/TreeMotion.spec.tsx | 30 +++++++++------ 4 files changed, 115 insertions(+), 75 deletions(-) create mode 100644 src/useUnmount.ts diff --git a/docs/examples/animation.jsx b/docs/examples/animation.jsx index 703d491b3..82d345a07 100644 --- a/docs/examples/animation.jsx +++ b/docs/examples/animation.jsx @@ -1,8 +1,9 @@ /* eslint no-console:0, react/no-danger: 0 */ +import { Provider } from 'rc-motion'; +import Tree from 'rc-tree'; +import React from 'react'; import '../../assets/index.less'; import './animation.less'; -import React from 'react'; -import Tree from 'rc-tree'; const STYLE = ` .rc-tree-child-tree { @@ -108,43 +109,56 @@ function getTreeData() { const Demo = () => { const treeRef = React.useRef(); + const [enableMotion, setEnableMotion] = React.useState(true); setTimeout(() => { treeRef.current.scrollTo({ key: '0-9-2' }); }, 100); return ( -
-

expanded

-