Skip to content

Commit

Permalink
refactor(tree): sync tree refactor from new common
Browse files Browse the repository at this point in the history
  • Loading branch information
uyarn committed Oct 16, 2023
1 parent 5f4f5cf commit f3a83b6
Show file tree
Hide file tree
Showing 11 changed files with 544 additions and 332 deletions.
2 changes: 1 addition & 1 deletion src/_common
Submodule _common updated 98 files
+8 −2 docs/web/api/cascader.md
+6 −0 docs/web/api/tabs.en-US.md
+6 −0 docs/web/api/tabs.md
+23 −1 docs/web/api/tag.en-US.md
+23 −7 docs/web/api/tag.md
+7 −0 docs/web/api/tree.md
+2 −1 js/common.ts
+2 −1 js/date-picker/utils.ts
+252 −218 js/tree/tree-node-model.ts
+3 −2 js/tree/tree-node.ts
+73 −62 js/tree/tree-store.ts
+7 −5 js/tree/types.ts
+2 −2 style/mobile/components/action-sheet/v2/_index.less
+6 −5 style/mobile/components/action-sheet/v2/_var.less
+1 −1 style/mobile/components/avatar/v2/_var.less
+3 −3 style/mobile/components/button/v2/_var.less
+2 −0 style/mobile/components/calendar/v2/_index.less
+6 −5 style/mobile/components/calendar/v2/_var.less
+2 −1 style/mobile/components/cascader/v2/_index.less
+5 −4 style/mobile/components/cascader/v2/_var.less
+4 −0 style/mobile/components/cell/v2/_index.less
+6 −6 style/mobile/components/cell/v2/_var.less
+2 −2 style/mobile/components/check-tag/v2/_var.less
+1 −1 style/mobile/components/checkbox/v2/_index.less
+6 −5 style/mobile/components/checkbox/v2/_var.less
+1 −1 style/mobile/components/collapse/v2/_index.less
+4 −3 style/mobile/components/collapse/v2/_var.less
+3 −3 style/mobile/components/count-down/v2/_var.less
+3 −3 style/mobile/components/dialog/v2/_var.less
+1 −1 style/mobile/components/divider/v2/_var.less
+2 −1 style/mobile/components/drawer/v2/_index.less
+1 −1 style/mobile/components/drawer/v2/_var.less
+2 −2 style/mobile/components/dropdown-menu/v2/_var.less
+2 −2 style/mobile/components/empty/_var.less
+1 −0 style/mobile/components/footer/_index.less
+3 −2 style/mobile/components/footer/_var.less
+3 −3 style/mobile/components/form/_index.less
+8 −2 style/mobile/components/grid-item/v2/_index.less
+2 −2 style/mobile/components/grid-item/v2/_var.less
+6 −0 style/mobile/components/grid/v2/_index.less
+2 −0 style/mobile/components/grid/v2/_var.less
+2 −2 style/mobile/components/image/v2/_var.less
+1 −1 style/mobile/components/indexes-anchor/v2/_var.less
+2 −2 style/mobile/components/indexes/v2/_var.less
+6 −2 style/mobile/components/input/v2/_index.less
+6 −6 style/mobile/components/input/v2/_var.less
+1 −1 style/mobile/components/link/v2/_var.less
+1 −1 style/mobile/components/loading/_index.less
+1 −0 style/mobile/components/loading/_var.less
+1 −1 style/mobile/components/loading/v2/_index.less
+1 −0 style/mobile/components/loading/v2/_var.less
+3 −3 style/mobile/components/message/v2/_index.less
+3 −2 style/mobile/components/message/v2/_var.less
+1 −1 style/mobile/components/navbar/v2/_var.less
+2 −2 style/mobile/components/notice-bar/v2/_var.less
+1 −1 style/mobile/components/overlay/v2/_var.less
+2 −2 style/mobile/components/picker/v2/_index.less
+4 −4 style/mobile/components/picker/v2/_var.less
+2 −2 style/mobile/components/popover/_var.less
+1 −1 style/mobile/components/pull-down-refresh/v2/_var.less
+2 −2 style/mobile/components/radio/v2/_var.less
+2 −2 style/mobile/components/rate/v2/_var.less
+2 −2 style/mobile/components/result/v2/_var.less
+5 −5 style/mobile/components/search/v2/_var.less
+1 −1 style/mobile/components/side-bar/v2/_index.less
+3 −2 style/mobile/components/side-bar/v2/_var.less
+2 −2 style/mobile/components/skeleton/v2/_var.less
+2 −2 style/mobile/components/slider/v2/_index.less
+3 −2 style/mobile/components/slider/v2/_var.less
+5 −5 style/mobile/components/step-item/v2/_var.less
+2 −2 style/mobile/components/stepper/v2/_var.less
+3 −0 style/mobile/components/swipe-cell/v2/_index.less
+1 −1 style/mobile/components/switch/v2/_index.less
+2 −2 style/mobile/components/switch/v2/_var.less
+1 −1 style/mobile/components/tab-bar-item/v2/_var.less
+1 −1 style/mobile/components/table/_var.less
+1 −1 style/mobile/components/tabs/v2/_index.less
+2 −2 style/mobile/components/tabs/v2/_var.less
+3 −3 style/mobile/components/tag/v2/_var.less
+5 −0 style/mobile/components/textarea/v2/_index.less
+5 −5 style/mobile/components/textarea/v2/_var.less
+2 −2 style/mobile/components/upload/v2/_var.less
+154 −0 style/mobile/theme/_dark.less
+1 −0 style/mobile/theme/_index.less
+6 −4 style/web/components/anchor/_index.less
+5 −2 style/web/components/badge/_index.less
+4 −0 style/web/components/badge/_var.less
+4 −0 style/web/components/breadcrumb/_index.less
+2 −1 style/web/components/cascader/_var.less
+7 −0 style/web/components/form/_mixin.less
+4 −1 style/web/components/list/_index.less
+0 −16 style/web/components/menu/_docs.less
+26 −6 style/web/components/menu/_index.less
+8 −0 style/web/components/select/_index.less
+13 −13 style/web/components/table/_index.less
+3 −0 style/web/components/tag-input/_index.less
+44 −21 style/web/components/tag/_index.less
+7 −2 style/web/components/tag/_var.less
138 changes: 32 additions & 106 deletions src/tree/Tree.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,27 @@
import React, {
forwardRef,
useState,
useImperativeHandle,
useMemo,
RefObject,
MouseEvent,
useRef,
useCallback,
} from 'react';
import React, { forwardRef, useImperativeHandle, useMemo, RefObject, useRef } from 'react';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import classNames from 'classnames';
import get from 'lodash/get';

import TreeNode from '../_common/js/tree/tree-node';
import { TreeOptionData, StyledProps, ComponentScrollToElementParams } from '../common';
import { TreeItemProps } from './interface';
import TreeItem from './TreeItem';
import log from '../_common/js/log';

import useControllable from './hooks/useControllable';
import { useStore } from './hooks/useStore';
import useTreeState from './hooks/useTreeState';
import useTreeStore from './hooks/useTreeStore';
import { useTreeConfig } from './hooks/useTreeConfig';
import { TreeDraggableContext } from './hooks/TreeDraggableContext';
import parseTNode from '../_util/parseTNode';
import { usePersistFn } from '../_util/usePersistFn';
import useTreeVirtualScroll from './hooks/useTreeVirtualScroll';

import type { TreeNodeState, TreeNodeValue, TypeTreeNodeData, TypeTreeNodeModel } from '../_common/js/tree/types';
import type { TreeInstanceFunctions, TdTreeProps } from './type';

export type TreeProps = TdTreeProps & StyledProps;

/**
* 树组件
*/
const Tree = forwardRef((props: TreeProps, ref: React.Ref<TreeInstanceFunctions>) => {
const { treeClassNames, transitionNames, transitionClassNames, transitionDuration, locale } = useTreeConfig();

// 可见节点集合
const [visibleNodes, setVisibleNodes] = useState([]);

const {
empty,
activable,
Expand All @@ -60,90 +42,51 @@ const Tree = forwardRef((props: TreeProps, ref: React.Ref<TreeInstanceFunctions>
style,
} = props;

const { value, onChange, expanded, onExpand, onActive, actived } = useControllable(props);

// 国际化文本初始化
const emptyText = locale('empty');

const store = useStore(
{
...props,
value,
onChange,
expanded,
onExpand,
onActive,
actived,
},
initial,
);

function initial() {
const nodes = store?.getNodes();
const newVisibleNodes = nodes?.filter((node) => node.visible);
setVisibleNodes(newVisibleNodes);
}
// 因为是被 useImperativeHandle 依赖的方法,使用 usePersistFn 变成持久化的。或者也可以使用 useCallback
const setExpanded = usePersistFn(
(
node: TreeNode,
isExpanded: boolean,
ctx: { e?: MouseEvent<HTMLDivElement>; trigger: 'node-click' | 'icon-click' | 'setItem' },
) => {
const { e, trigger } = ctx;
const expanded = node.setExpanded(isExpanded);
const treeNodeModel = node?.getModel();
(e || trigger) && onExpand?.(expanded, { node: treeNodeModel, e, trigger });
return expanded;
},
);
const treeRef = useRef(null);

const {
value,
setChecked,
toggleChecked,
expanded,
setExpanded,
toggleExpanded,
setActived,
actived,
toggleActived,
updateState,
visibleNodes,
allNodes,
} = useTreeState(props);

const { store } = useTreeStore(props, { value, expanded, actived, updateState });

const {
visibleData,
isVirtual,
treeNodeStyle: virtualTreeNodeStyle,
cursorStyle,
handleRowMounted,
scrollToElement,
handleScrollToElement,
} = useTreeVirtualScroll({
treeRef,
scroll,
data: visibleNodes,
data: allNodes,
});

const setActived = usePersistFn(
(
node: TreeNode,
isActived: boolean,
ctx: { e?: MouseEvent<HTMLDivElement>; trigger: 'node-click' | 'setItem' },
) => {
const actived = node.setActived(isActived);
const treeNodeModel = node?.getModel();
onActive?.(actived, { node: treeNodeModel, ...ctx });
return actived;
},
);

const setChecked = usePersistFn(
(node: TreeNode, isChecked: boolean, ctx: { e?: any; trigger: 'node-click' | 'setItem' }) => {
const checked = node.setChecked(isChecked);
const treeNodeModel = node?.getModel();
onChange?.(checked, { node: treeNodeModel, ...ctx });
return checked;
},
);

const handleItemClick: TreeItemProps['onClick'] = (node, options) => {
if (!node) {
return;
}
const isDisabled = disabled || node.disabled;
const { expand, active, e, trigger } = options;
if (expand) setExpanded(node, !node.isExpanded(), { e, trigger });
if (expand) toggleExpanded(node, { e, trigger });

if (active && !isDisabled) {
setActived(node, !node.isActived(), { e, trigger: 'node-click' });
toggleActived(node, { e, trigger: 'node-click' });
const treeNodeModel = node?.getModel();
onClick?.({ node: treeNodeModel, e });
}
Expand All @@ -153,33 +96,15 @@ const Tree = forwardRef((props: TreeProps, ref: React.Ref<TreeInstanceFunctions>
if (!node || disabled || node.disabled) {
return;
}
setChecked(node, !node.isChecked(), { ...ctx, trigger: 'node-click' });
toggleChecked(node, { ...ctx, trigger: 'node-click' });
};
const handleScrollToElement = useCallback(
(params: ComponentScrollToElementParams) => {
let { index } = params;

if (!index && index !== 0) {
if (!params.key) {
log.error('Tree', 'scrollToElement: one of `index` or `key` must exist.');
return;
}
const data = isVirtual ? visibleData : visibleNodes;
index = data?.findIndex((item) => [get(item.data, 'key'), get(item.data, 'value')].includes(params.key));
if (index < 0) {
log.error('Tree', `${params.key} does not exist in data, check \`key\` or \`data\` please.`);
}
}
scrollToElement({ ...params, index });
},
[scrollToElement, isVirtual, visibleData, visibleNodes],
);
/** 对外暴露的公共方法 * */
// treeRef expose methods
useImperativeHandle<unknown, TreeInstanceFunctions>(
ref,
() => ({
store,
scrollTo: (p: ComponentScrollToElementParams) => handleScrollToElement(p),
scrollTo: (p: ComponentScrollToElementParams) => handleScrollToElement(p), // 指定滚动到具体节点
appendTo(value, newData) {
let list = [];
if (Array.isArray(newData)) {
Expand Down Expand Up @@ -232,21 +157,22 @@ const Tree = forwardRef((props: TreeProps, ref: React.Ref<TreeInstanceFunctions>
const spec = options;
if (node && spec) {
if ('expanded' in options) {
setExpanded(node, spec.expanded, { trigger: 'setItem' });
toggleExpanded(node, { trigger: 'setItem' });
delete spec.expanded;
}
if ('actived' in options) {
setActived(node, spec.actived, { trigger: 'setItem' });
toggleActived(node, { trigger: 'setItem' });
delete spec.actived;
}
if ('checked' in options) {
setChecked(node, spec.checked, { trigger: 'setItem' });
toggleChecked(node, { trigger: 'setItem' });
delete spec.checked;
}
node.set(spec);
}
},
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[store, setExpanded, setActived, setChecked, handleScrollToElement],
);

Expand Down Expand Up @@ -342,7 +268,7 @@ const Tree = forwardRef((props: TreeProps, ref: React.Ref<TreeInstanceFunctions>
[treeClassNames.treeCheckable]: checkable,
[treeClassNames.treeFx]: transition,
[treeClassNames.treeBlockNode]: expandOnClickNode,
[treeClassNames.treeVscroll]: props.scroll, // 开启虚拟滚动就要有overflow 否则低于 threshold 无法正常运行 scrollto
[treeClassNames.treeVscroll]: props.scroll, // 开启虚拟滚动就要有 overflow, 否则低于 threshold 无法正常运行 scrollTo
})}
style={style}
ref={treeRef}
Expand Down
9 changes: 4 additions & 5 deletions src/tree/TreeItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,21 @@ import React, {
import classNames from 'classnames';
import isFunction from 'lodash/isFunction';
import { CaretRightSmallIcon as TdCaretRightSmallIcon } from 'tdesign-icons-react';

import Loading from '../loading';
import Checkbox from '../checkbox';
import TreeNode from '../_common/js/tree/tree-node';

import useRipple from '../_util/useRipple';
import useDomRefCallback from '../hooks/useDomRefCallback';
import useGlobalIcon from '../hooks/useGlobalIcon';
import TreeNode from '../_common/js/tree/tree-node';
import Checkbox from '../checkbox';
import { useTreeConfig } from './hooks/useTreeConfig';
import useDraggable from './hooks/useDraggable';
import composeRefs from '../_util/composeRefs';
import useConfig from '../hooks/useConfig';

import type { TreeItemProps } from './interface';

/**
* 树节点组件
*/
const TreeItem = forwardRef(
(
props: TreeItemProps & {
Expand Down
21 changes: 0 additions & 21 deletions src/tree/hooks/useControllable.ts

This file was deleted.

3 changes: 2 additions & 1 deletion src/tree/hooks/useDraggable.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import throttle from 'lodash/throttle';
import { RefObject, DragEvent, useState, useRef } from 'react';
import throttle from 'lodash/throttle';

import { TreeNode } from '../../_common/js/tree/tree-node';
import { useTreeDraggableContext } from './TreeDraggableContext';
import { DropPosition } from '../interface';
Expand Down
Loading

0 comments on commit f3a83b6

Please sign in to comment.