feat: tree
parent
98755f332c
commit
54cdc3ff40
|
@ -6,6 +6,7 @@ import { computed, defineComponent, ref, shallowRef, watch } from 'vue';
|
||||||
import VirtualList from '../vc-virtual-list';
|
import VirtualList from '../vc-virtual-list';
|
||||||
import type { FlattenNode, DataEntity, DataNode, ScrollTo } from './interface';
|
import type { FlattenNode, DataEntity, DataNode, ScrollTo } from './interface';
|
||||||
import MotionTreeNode from './MotionTreeNode';
|
import MotionTreeNode from './MotionTreeNode';
|
||||||
|
import type { NodeListProps } from './props';
|
||||||
import { nodeListProps } from './props';
|
import { nodeListProps } from './props';
|
||||||
import { findExpandedKeys, getExpandRange } from './utils/diffUtil';
|
import { findExpandedKeys, getExpandRange } from './utils/diffUtil';
|
||||||
import { getTreeNodeProps, getKey } from './utils/treeUtil';
|
import { getTreeNodeProps, getKey } from './utils/treeUtil';
|
||||||
|
@ -35,6 +36,7 @@ export const MotionEntity: DataEntity = {
|
||||||
index: 0,
|
index: 0,
|
||||||
pos: '0',
|
pos: '0',
|
||||||
node: MotionNode,
|
node: MotionNode,
|
||||||
|
nodes: [MotionNode],
|
||||||
};
|
};
|
||||||
|
|
||||||
const MotionFlattenData: FlattenNode = {
|
const MotionFlattenData: FlattenNode = {
|
||||||
|
@ -208,7 +210,7 @@ export default defineComponent({
|
||||||
onListChangeEnd,
|
onListChangeEnd,
|
||||||
|
|
||||||
...domProps
|
...domProps
|
||||||
} = { ...props, ...attrs };
|
} = { ...props, ...attrs } as NodeListProps;
|
||||||
|
|
||||||
const treeNodeRequiredProps = {
|
const treeNodeRequiredProps = {
|
||||||
expandedKeys,
|
expandedKeys,
|
||||||
|
@ -269,6 +271,15 @@ export default defineComponent({
|
||||||
itemHeight={itemHeight}
|
itemHeight={itemHeight}
|
||||||
prefixCls={`${prefixCls}-list`}
|
prefixCls={`${prefixCls}-list`}
|
||||||
ref={listRef}
|
ref={listRef}
|
||||||
|
onVisibleChange={(originList, fullList) => {
|
||||||
|
const originSet = new Set(originList);
|
||||||
|
const restList = fullList.filter(item => !originSet.has(item));
|
||||||
|
|
||||||
|
// Motion node is not render. Skip motion
|
||||||
|
if (restList.some(item => itemKey(item) === MOTION_KEY)) {
|
||||||
|
onMotionEnd();
|
||||||
|
}
|
||||||
|
}}
|
||||||
v-slots={{
|
v-slots={{
|
||||||
default: (treeNode: FlattenNode) => {
|
default: (treeNode: FlattenNode) => {
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import type { NodeMouseEventHandler, NodeDragEventHandler } from './contextTypes';
|
import type { NodeMouseEventHandler, NodeDragEventHandler } from './contextTypes';
|
||||||
import { TreeContext } from './contextTypes';
|
import { TreeContext } from './contextTypes';
|
||||||
import {
|
import {
|
||||||
getDataAndAria,
|
|
||||||
getDragChildrenKeys,
|
getDragChildrenKeys,
|
||||||
parseCheckedKeys,
|
parseCheckedKeys,
|
||||||
conductExpandParent,
|
conductExpandParent,
|
||||||
|
@ -34,11 +33,19 @@ import {
|
||||||
watchEffect,
|
watchEffect,
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
||||||
import type { CheckInfo } from './props';
|
import type { CheckInfo, DraggableFn } from './props';
|
||||||
import { treeProps } from './props';
|
import { treeProps } from './props';
|
||||||
import { warning } from '../vc-util/warning';
|
import { warning } from '../vc-util/warning';
|
||||||
import KeyCode from '../_util/KeyCode';
|
import KeyCode from '../_util/KeyCode';
|
||||||
import classNames from '../_util/classNames';
|
import classNames from '../_util/classNames';
|
||||||
|
import pickAttrs from '../_util/pickAttrs';
|
||||||
|
|
||||||
|
const MAX_RETRY_TIMES = 10;
|
||||||
|
|
||||||
|
export type DraggableConfig = {
|
||||||
|
icon?: any;
|
||||||
|
nodeDraggable?: DraggableFn;
|
||||||
|
};
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Tree',
|
name: 'Tree',
|
||||||
|
@ -74,9 +81,9 @@ export default defineComponent({
|
||||||
const loadedKeys = shallowRef([]);
|
const loadedKeys = shallowRef([]);
|
||||||
const loadingKeys = shallowRef([]);
|
const loadingKeys = shallowRef([]);
|
||||||
const expandedKeys = shallowRef([]);
|
const expandedKeys = shallowRef([]);
|
||||||
|
const loadingRetryTimes: Record<Key, number> = {};
|
||||||
const dragState = reactive({
|
const dragState = reactive({
|
||||||
dragging: false,
|
draggingNodeKey: null,
|
||||||
dragChildrenKeys: [],
|
dragChildrenKeys: [],
|
||||||
|
|
||||||
// dropTargetKey is the key of abstract-drop-node
|
// dropTargetKey is the key of abstract-drop-node
|
||||||
|
@ -111,6 +118,8 @@ export default defineComponent({
|
||||||
|
|
||||||
let dragNode: DragNodeEvent = null;
|
let dragNode: DragNodeEvent = null;
|
||||||
|
|
||||||
|
let currentMouseOverDroppableNodeKey = null;
|
||||||
|
|
||||||
const treeNodeRequiredProps = computed(() => {
|
const treeNodeRequiredProps = computed(() => {
|
||||||
return {
|
return {
|
||||||
expandedKeys: expandedKeys.value || [],
|
expandedKeys: expandedKeys.value || [],
|
||||||
|
@ -219,6 +228,17 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const resetDragState = () => {
|
||||||
|
Object.assign(dragState, {
|
||||||
|
dragOverNodeKey: null,
|
||||||
|
dropPosition: null,
|
||||||
|
dropLevelOffset: null,
|
||||||
|
dropTargetKey: null,
|
||||||
|
dropContainerKey: null,
|
||||||
|
dropTargetPos: null,
|
||||||
|
dropAllowed: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
const scrollTo: ScrollTo = scroll => {
|
const scrollTo: ScrollTo = scroll => {
|
||||||
listRef.value.scrollTo(scroll);
|
listRef.value.scrollTo(scroll);
|
||||||
};
|
};
|
||||||
|
@ -231,9 +251,9 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanDragState = () => {
|
const cleanDragState = () => {
|
||||||
if (dragState.dragging) {
|
if (dragState.draggingNodeKey !== null) {
|
||||||
Object.assign(dragState, {
|
Object.assign(dragState, {
|
||||||
dragging: false,
|
draggingNodeKey: null,
|
||||||
dropPosition: null,
|
dropPosition: null,
|
||||||
dropContainerKey: null,
|
dropContainerKey: null,
|
||||||
dropTargetKey: null,
|
dropTargetKey: null,
|
||||||
|
@ -243,6 +263,7 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
dragStartMousePosition = null;
|
dragStartMousePosition = null;
|
||||||
|
currentMouseOverDroppableNodeKey = null;
|
||||||
};
|
};
|
||||||
// if onNodeDragEnd is called, onWindowDragEnd won't be called since stopPropagation() is called
|
// if onNodeDragEnd is called, onWindowDragEnd won't be called since stopPropagation() is called
|
||||||
const onNodeDragEnd: NodeDragEventHandler = (event, node, outsideTree = false) => {
|
const onNodeDragEnd: NodeDragEventHandler = (event, node, outsideTree = false) => {
|
||||||
|
@ -277,7 +298,7 @@ export default defineComponent({
|
||||||
|
|
||||||
const newExpandedKeys = arrDel(expandedKeys.value, eventKey);
|
const newExpandedKeys = arrDel(expandedKeys.value, eventKey);
|
||||||
|
|
||||||
dragState.dragging = true;
|
dragState.draggingNodeKey = eventKey;
|
||||||
dragState.dragChildrenKeys = getDragChildrenKeys(eventKey, keyEntities.value);
|
dragState.dragChildrenKeys = getDragChildrenKeys(eventKey, keyEntities.value);
|
||||||
indent.value = listRef.value.getIndentWidth();
|
indent.value = listRef.value.getIndentWidth();
|
||||||
|
|
||||||
|
@ -296,9 +317,18 @@ export default defineComponent({
|
||||||
* Better for use mouse move event to refresh drag state.
|
* Better for use mouse move event to refresh drag state.
|
||||||
* But let's just keep it to avoid event trigger logic change.
|
* But let's just keep it to avoid event trigger logic change.
|
||||||
*/
|
*/
|
||||||
const onNodeDragEnter = (event: MouseEvent, node: DragNodeEvent) => {
|
const onNodeDragEnter = (event: DragEvent, node: DragNodeEvent) => {
|
||||||
const { onDragenter, onExpand, allowDrop, direction } = props;
|
const { onDragenter, onExpand, allowDrop, direction } = props;
|
||||||
|
const { pos, eventKey } = node;
|
||||||
|
// record the key of node which is latest entered, used in dragleave event.
|
||||||
|
if (currentMouseOverDroppableNodeKey !== eventKey) {
|
||||||
|
currentMouseOverDroppableNodeKey = eventKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dragNode) {
|
||||||
|
resetDragState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const {
|
const {
|
||||||
dropPosition,
|
dropPosition,
|
||||||
dropLevelOffset,
|
dropLevelOffset,
|
||||||
|
@ -321,21 +351,12 @@ export default defineComponent({
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!dragNode ||
|
|
||||||
// don't allow drop inside its children
|
// don't allow drop inside its children
|
||||||
dragState.dragChildrenKeys.indexOf(dropTargetKey) !== -1 ||
|
dragState.dragChildrenKeys.indexOf(dropTargetKey) !== -1 ||
|
||||||
// don't allow drop when drop is not allowed caculated by calcDropPosition
|
// don't allow drop when drop is not allowed caculated by calcDropPosition
|
||||||
!dropAllowed
|
!dropAllowed
|
||||||
) {
|
) {
|
||||||
Object.assign(dragState, {
|
resetDragState();
|
||||||
dragOverNodeKey: null,
|
|
||||||
dropPosition: null,
|
|
||||||
dropLevelOffset: null,
|
|
||||||
dropTargetKey: null,
|
|
||||||
dropContainerKey: null,
|
|
||||||
dropTargetPos: null,
|
|
||||||
dropAllowed: false,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,8 +373,8 @@ export default defineComponent({
|
||||||
// since if logic is on the bottom
|
// since if logic is on the bottom
|
||||||
// it will be blocked by abstract dragover node check
|
// it will be blocked by abstract dragover node check
|
||||||
// => if you dragenter from top, you mouse will still be consider as in the top node
|
// => if you dragenter from top, you mouse will still be consider as in the top node
|
||||||
delayedDragEnterLogic[node.pos] = window.setTimeout(() => {
|
delayedDragEnterLogic[pos] = window.setTimeout(() => {
|
||||||
if (!dragState.dragging) return;
|
if (dragState.draggingNodeKey === null) return;
|
||||||
|
|
||||||
let newExpandedKeys = [...expandedKeys.value];
|
let newExpandedKeys = [...expandedKeys.value];
|
||||||
const entity = keyEntities.value[node.eventKey];
|
const entity = keyEntities.value[node.eventKey];
|
||||||
|
@ -375,15 +396,7 @@ export default defineComponent({
|
||||||
|
|
||||||
// Skip if drag node is self
|
// Skip if drag node is self
|
||||||
if (dragNode.eventKey === dropTargetKey && dropLevelOffset === 0) {
|
if (dragNode.eventKey === dropTargetKey && dropLevelOffset === 0) {
|
||||||
Object.assign(dragState, {
|
resetDragState();
|
||||||
dragOverNodeKey: null,
|
|
||||||
dropPosition: null,
|
|
||||||
dropLevelOffset: null,
|
|
||||||
dropTargetKey: null,
|
|
||||||
dropContainerKey: null,
|
|
||||||
dropTargetPos: null,
|
|
||||||
dropAllowed: false,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,9 +420,12 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onNodeDragOver = (event: MouseEvent, node: DragNodeEvent) => {
|
const onNodeDragOver = (event: DragEvent, node: DragNodeEvent) => {
|
||||||
const { onDragover, allowDrop, direction } = props;
|
const { onDragover, allowDrop, direction } = props;
|
||||||
|
|
||||||
|
if (!dragNode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const {
|
const {
|
||||||
dropPosition,
|
dropPosition,
|
||||||
dropLevelOffset,
|
dropLevelOffset,
|
||||||
|
@ -431,7 +447,7 @@ export default defineComponent({
|
||||||
direction,
|
direction,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!dragNode || dragState.dragChildrenKeys.indexOf(dropTargetKey) !== -1 || !dropAllowed) {
|
if (dragState.dragChildrenKeys.indexOf(dropTargetKey) !== -1 || !dropAllowed) {
|
||||||
// don't allow drop inside its children
|
// don't allow drop inside its children
|
||||||
// don't allow drop when drop is not allowed caculated by calcDropPosition
|
// don't allow drop when drop is not allowed caculated by calcDropPosition
|
||||||
return;
|
return;
|
||||||
|
@ -451,15 +467,7 @@ export default defineComponent({
|
||||||
dragState.dragOverNodeKey === null
|
dragState.dragOverNodeKey === null
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Object.assign(dragState, {
|
resetDragState();
|
||||||
dropPosition: null,
|
|
||||||
dropLevelOffset: null,
|
|
||||||
dropTargetKey: null,
|
|
||||||
dropContainerKey: null,
|
|
||||||
dropTargetPos: null,
|
|
||||||
dropAllowed: false,
|
|
||||||
dragOverNodeKey: null,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
!(
|
!(
|
||||||
|
@ -489,13 +497,23 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
|
|
||||||
const onNodeDragLeave: NodeDragEventHandler = (event, node) => {
|
const onNodeDragLeave: NodeDragEventHandler = (event, node) => {
|
||||||
|
// if it is outside the droppable area
|
||||||
|
// currentMouseOverDroppableNodeKey will be updated in dragenter event when into another droppable receiver.
|
||||||
|
if (
|
||||||
|
currentMouseOverDroppableNodeKey === node.eventKey &&
|
||||||
|
!(event.currentTarget as any).contains(event.relatedTarget as Node)
|
||||||
|
) {
|
||||||
|
resetDragState();
|
||||||
|
currentMouseOverDroppableNodeKey = null;
|
||||||
|
}
|
||||||
|
|
||||||
const { onDragleave } = props;
|
const { onDragleave } = props;
|
||||||
|
|
||||||
if (onDragleave) {
|
if (onDragleave) {
|
||||||
onDragleave({ event, node: node.eventData });
|
onDragleave({ event, node: node.eventData });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const onNodeDrop = (event: MouseEvent, _node, outsideTree = false) => {
|
const onNodeDrop = (event: DragEvent, _node, outsideTree = false) => {
|
||||||
const { dragChildrenKeys, dropPosition, dropTargetKey, dropTargetPos, dropAllowed } =
|
const { dragChildrenKeys, dropPosition, dropTargetKey, dropTargetPos, dropAllowed } =
|
||||||
dragState;
|
dragState;
|
||||||
|
|
||||||
|
@ -666,11 +684,11 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onNodeLoad = (treeNode: EventDataNode) =>
|
const onNodeLoad = (treeNode: EventDataNode) => {
|
||||||
new Promise<void>((resolve, reject) => {
|
const key = treeNode[fieldNames.value.key];
|
||||||
|
const loadPromise = new Promise<void>((resolve, reject) => {
|
||||||
// We need to get the latest state of loading/loaded keys
|
// We need to get the latest state of loading/loaded keys
|
||||||
const { loadData, onLoad } = props;
|
const { loadData, onLoad } = props;
|
||||||
const key = treeNode[fieldNames.value.key];
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!loadData ||
|
!loadData ||
|
||||||
|
@ -705,12 +723,28 @@ export default defineComponent({
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
const newLoadingKeys = arrDel(loadingKeys.value, key);
|
const newLoadingKeys = arrDel(loadingKeys.value, key);
|
||||||
loadingKeys.value = newLoadingKeys;
|
loadingKeys.value = newLoadingKeys;
|
||||||
|
|
||||||
|
// If exceed max retry times, we give up retry
|
||||||
|
loadingRetryTimes[key] = (loadingRetryTimes[key] || 0) + 1;
|
||||||
|
if (loadingRetryTimes[key] >= MAX_RETRY_TIMES) {
|
||||||
|
warning(false, 'Retry for `loadData` many times but still failed. No more retry.');
|
||||||
|
const newLoadedKeys = arrAdd(loadedKeys.value, key);
|
||||||
|
if (props.loadedKeys === undefined) {
|
||||||
|
loadedKeys.value = newLoadedKeys;
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
|
||||||
reject(e);
|
reject(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
loadingKeys.value = arrAdd(loadingKeys.value, key);
|
loadingKeys.value = arrAdd(loadingKeys.value, key);
|
||||||
});
|
});
|
||||||
|
// Not care warning if we ignore this
|
||||||
|
loadPromise.catch(() => {});
|
||||||
|
|
||||||
|
return loadPromise;
|
||||||
|
};
|
||||||
const onNodeMouseEnter: NodeMouseEventHandler = (event, node) => {
|
const onNodeMouseEnter: NodeMouseEventHandler = (event, node) => {
|
||||||
const { onMouseenter } = props;
|
const { onMouseenter } = props;
|
||||||
if (onMouseenter) {
|
if (onMouseenter) {
|
||||||
|
@ -968,7 +1002,7 @@ export default defineComponent({
|
||||||
// focused,
|
// focused,
|
||||||
// flattenNodes,
|
// flattenNodes,
|
||||||
// keyEntities,
|
// keyEntities,
|
||||||
dragging,
|
draggingNodeKey,
|
||||||
// activeKey,
|
// activeKey,
|
||||||
dropLevelOffset,
|
dropLevelOffset,
|
||||||
dropContainerKey,
|
dropContainerKey,
|
||||||
|
@ -1003,7 +1037,27 @@ export default defineComponent({
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const { class: className, style } = attrs;
|
const { class: className, style } = attrs;
|
||||||
const domProps = getDataAndAria({ ...props, ...attrs });
|
const domProps = pickAttrs(
|
||||||
|
{ ...props, ...attrs },
|
||||||
|
{
|
||||||
|
aria: true,
|
||||||
|
data: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// It's better move to hooks but we just simply keep here
|
||||||
|
let draggableConfig: DraggableConfig;
|
||||||
|
if (draggable) {
|
||||||
|
if (typeof draggable === 'object') {
|
||||||
|
draggableConfig = draggable;
|
||||||
|
} else if (typeof draggable === 'function') {
|
||||||
|
draggableConfig = {
|
||||||
|
nodeDraggable: draggable,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
draggableConfig = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<TreeContext
|
<TreeContext
|
||||||
value={{
|
value={{
|
||||||
|
@ -1012,7 +1066,8 @@ export default defineComponent({
|
||||||
showIcon,
|
showIcon,
|
||||||
icon,
|
icon,
|
||||||
switcherIcon,
|
switcherIcon,
|
||||||
draggable,
|
draggable: draggableConfig,
|
||||||
|
draggingNodeKey,
|
||||||
checkable,
|
checkable,
|
||||||
customCheckable: slots.checkable,
|
customCheckable: slots.checkable,
|
||||||
checkStrictly,
|
checkStrictly,
|
||||||
|
@ -1065,7 +1120,7 @@ export default defineComponent({
|
||||||
selectable={selectable}
|
selectable={selectable}
|
||||||
checkable={!!checkable}
|
checkable={!!checkable}
|
||||||
motion={motion}
|
motion={motion}
|
||||||
dragging={dragging}
|
dragging={draggingNodeKey !== null}
|
||||||
height={height}
|
height={height}
|
||||||
itemHeight={itemHeight}
|
itemHeight={itemHeight}
|
||||||
virtual={virtual}
|
virtual={virtual}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { useInjectTreeContext } from './contextTypes';
|
import { useInjectTreeContext } from './contextTypes';
|
||||||
import { getDataAndAria } from './util';
|
|
||||||
import Indent from './Indent';
|
import Indent from './Indent';
|
||||||
import { convertNodePropsToEventData } from './utils/treeUtil';
|
import { convertNodePropsToEventData } from './utils/treeUtil';
|
||||||
import {
|
import {
|
||||||
|
@ -16,6 +15,7 @@ import classNames from '../_util/classNames';
|
||||||
import { warning } from '../vc-util/warning';
|
import { warning } from '../vc-util/warning';
|
||||||
import type { DragNodeEvent, Key } from './interface';
|
import type { DragNodeEvent, Key } from './interface';
|
||||||
import pick from 'lodash-es/pick';
|
import pick from 'lodash-es/pick';
|
||||||
|
import pickAttrs from '../_util/pickAttrs';
|
||||||
|
|
||||||
const ICON_OPEN = 'open';
|
const ICON_OPEN = 'open';
|
||||||
const ICON_CLOSE = 'close';
|
const ICON_CLOSE = 'close';
|
||||||
|
@ -248,6 +248,20 @@ export default defineComponent({
|
||||||
onNodeExpand(e, eventData.value);
|
onNodeExpand(e, eventData.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isDraggable = () => {
|
||||||
|
const { data } = props;
|
||||||
|
const { draggable } = context.value;
|
||||||
|
return !!(draggable && (!draggable.nodeDraggable || draggable.nodeDraggable(data)));
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================== Render: Drag Handler ====================
|
||||||
|
const renderDragHandler = () => {
|
||||||
|
const { draggable, prefixCls } = context.value;
|
||||||
|
return draggable?.icon ? (
|
||||||
|
<span class={`${prefixCls}-draggable-icon`}>{draggable.icon}</span>
|
||||||
|
) : null;
|
||||||
|
};
|
||||||
|
|
||||||
const renderSwitcherIconDom = () => {
|
const renderSwitcherIconDom = () => {
|
||||||
const {
|
const {
|
||||||
switcherIcon: switcherIconFromProps = slots.switcherIcon ||
|
switcherIcon: switcherIconFromProps = slots.switcherIcon ||
|
||||||
|
@ -368,9 +382,9 @@ export default defineComponent({
|
||||||
dragOverNodeKey,
|
dragOverNodeKey,
|
||||||
direction,
|
direction,
|
||||||
} = context.value;
|
} = context.value;
|
||||||
const mergedDraggable = draggable !== false;
|
const rootDraggable = draggable !== false;
|
||||||
// allowDrop is calculated in Tree.tsx, there is no need for calc it here
|
// allowDrop is calculated in Tree.tsx, there is no need for calc it here
|
||||||
const showIndicator = !disabled && mergedDraggable && dragOverNodeKey === eventKey;
|
const showIndicator = !disabled && rootDraggable && dragOverNodeKey === eventKey;
|
||||||
return showIndicator
|
return showIndicator
|
||||||
? dropIndicatorRender({ dropPosition, dropLevelOffset, indent, prefixCls, direction })
|
? dropIndicatorRender({ dropPosition, dropLevelOffset, indent, prefixCls, direction })
|
||||||
: null;
|
: null;
|
||||||
|
@ -396,12 +410,10 @@ export default defineComponent({
|
||||||
prefixCls,
|
prefixCls,
|
||||||
showIcon,
|
showIcon,
|
||||||
icon: treeIcon,
|
icon: treeIcon,
|
||||||
draggable,
|
|
||||||
loadData,
|
loadData,
|
||||||
// slots: contextSlots,
|
// slots: contextSlots,
|
||||||
} = context.value;
|
} = context.value;
|
||||||
const disabled = isDisabled.value;
|
const disabled = isDisabled.value;
|
||||||
const mergedDraggable = typeof draggable === 'function' ? draggable(data) : draggable;
|
|
||||||
|
|
||||||
const wrapClass = `${prefixCls}-node-content-wrapper`;
|
const wrapClass = `${prefixCls}-node-content-wrapper`;
|
||||||
|
|
||||||
|
@ -443,16 +455,12 @@ export default defineComponent({
|
||||||
`${wrapClass}`,
|
`${wrapClass}`,
|
||||||
`${wrapClass}-${nodeState.value || 'normal'}`,
|
`${wrapClass}-${nodeState.value || 'normal'}`,
|
||||||
!disabled && (selected || dragNodeHighlight.value) && `${prefixCls}-node-selected`,
|
!disabled && (selected || dragNodeHighlight.value) && `${prefixCls}-node-selected`,
|
||||||
!disabled && mergedDraggable && 'draggable',
|
|
||||||
)}
|
)}
|
||||||
draggable={(!disabled && mergedDraggable) || undefined}
|
|
||||||
aria-grabbed={(!disabled && mergedDraggable) || undefined}
|
|
||||||
onMouseenter={onMouseEnter}
|
onMouseenter={onMouseEnter}
|
||||||
onMouseleave={onMouseLeave}
|
onMouseleave={onMouseLeave}
|
||||||
onContextmenu={onContextmenu}
|
onContextmenu={onContextmenu}
|
||||||
onClick={onSelectorClick}
|
onClick={onSelectorClick}
|
||||||
onDblclick={onSelectorDoubleClick}
|
onDblclick={onSelectorDoubleClick}
|
||||||
onDragstart={mergedDraggable ? onDragStart : undefined}
|
|
||||||
>
|
>
|
||||||
{$icon}
|
{$icon}
|
||||||
{$title}
|
{$title}
|
||||||
|
@ -478,15 +486,28 @@ export default defineComponent({
|
||||||
active,
|
active,
|
||||||
data,
|
data,
|
||||||
onMousemove,
|
onMousemove,
|
||||||
|
selectable,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = { ...props, ...attrs };
|
} = { ...props, ...attrs };
|
||||||
const { prefixCls, filterTreeNode, draggable, keyEntities, dropContainerKey, dropTargetKey } =
|
const {
|
||||||
context.value;
|
prefixCls,
|
||||||
|
filterTreeNode,
|
||||||
|
keyEntities,
|
||||||
|
dropContainerKey,
|
||||||
|
dropTargetKey,
|
||||||
|
draggingNodeKey,
|
||||||
|
} = context.value;
|
||||||
const disabled = isDisabled.value;
|
const disabled = isDisabled.value;
|
||||||
const dataOrAriaAttributeProps = getDataAndAria(otherProps);
|
const dataOrAriaAttributeProps = pickAttrs(otherProps, { aria: true, data: true });
|
||||||
const { level } = keyEntities[eventKey] || {};
|
const { level } = keyEntities[eventKey] || {};
|
||||||
const isEndNode = isEnd[isEnd.length - 1];
|
const isEndNode = isEnd[isEnd.length - 1];
|
||||||
const mergedDraggable = typeof draggable === 'function' ? draggable(data) : draggable;
|
|
||||||
|
const mergedDraggable = isDraggable();
|
||||||
|
const draggableWithoutDisabled = !disabled && mergedDraggable;
|
||||||
|
|
||||||
|
const dragging = draggingNodeKey === eventKey;
|
||||||
|
const ariaSelected = selectable !== undefined ? { 'aria-selected': !!selectable } : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={domRef}
|
ref={domRef}
|
||||||
|
@ -499,7 +520,9 @@ export default defineComponent({
|
||||||
[`${prefixCls}-treenode-loading`]: loading,
|
[`${prefixCls}-treenode-loading`]: loading,
|
||||||
[`${prefixCls}-treenode-active`]: active,
|
[`${prefixCls}-treenode-active`]: active,
|
||||||
[`${prefixCls}-treenode-leaf-last`]: isEndNode,
|
[`${prefixCls}-treenode-leaf-last`]: isEndNode,
|
||||||
|
[`${prefixCls}-treenode-draggable`]: draggableWithoutDisabled,
|
||||||
|
|
||||||
|
dragging,
|
||||||
'drop-target': dropTargetKey === eventKey,
|
'drop-target': dropTargetKey === eventKey,
|
||||||
'drop-container': dropContainerKey === eventKey,
|
'drop-container': dropContainerKey === eventKey,
|
||||||
'drag-over': !disabled && dragOver,
|
'drag-over': !disabled && dragOver,
|
||||||
|
@ -508,15 +531,22 @@ export default defineComponent({
|
||||||
'filter-node': filterTreeNode && filterTreeNode(eventData.value),
|
'filter-node': filterTreeNode && filterTreeNode(eventData.value),
|
||||||
})}
|
})}
|
||||||
style={attrs.style}
|
style={attrs.style}
|
||||||
|
// Draggable config
|
||||||
|
draggable={draggableWithoutDisabled}
|
||||||
|
aria-grabbed={dragging}
|
||||||
|
onDragstart={draggableWithoutDisabled ? onDragStart : undefined}
|
||||||
|
// Drop config
|
||||||
onDragenter={mergedDraggable ? onDragEnter : undefined}
|
onDragenter={mergedDraggable ? onDragEnter : undefined}
|
||||||
onDragover={mergedDraggable ? onDragOver : undefined}
|
onDragover={mergedDraggable ? onDragOver : undefined}
|
||||||
onDragleave={mergedDraggable ? onDragLeave : undefined}
|
onDragleave={mergedDraggable ? onDragLeave : undefined}
|
||||||
onDrop={mergedDraggable ? onDrop : undefined}
|
onDrop={mergedDraggable ? onDrop : undefined}
|
||||||
onDragend={mergedDraggable ? onDragEnd : undefined}
|
onDragend={mergedDraggable ? onDragEnd : undefined}
|
||||||
onMousemove={onMousemove}
|
onMousemove={onMousemove}
|
||||||
|
{...ariaSelected}
|
||||||
{...dataOrAriaAttributeProps}
|
{...dataOrAriaAttributeProps}
|
||||||
>
|
>
|
||||||
<Indent prefixCls={prefixCls} level={level} isStart={isStart} isEnd={isEnd} />
|
<Indent prefixCls={prefixCls} level={level} isStart={isStart} isEnd={isEnd} />
|
||||||
|
{renderDragHandler()}
|
||||||
{renderSwitcher()}
|
{renderSwitcher()}
|
||||||
{renderCheckbox()}
|
{renderCheckbox()}
|
||||||
{renderSelector()}
|
{renderSelector()}
|
||||||
|
|
|
@ -12,22 +12,23 @@ import type {
|
||||||
DataEntity,
|
DataEntity,
|
||||||
EventDataNode,
|
EventDataNode,
|
||||||
DragNodeEvent,
|
DragNodeEvent,
|
||||||
DataNode,
|
|
||||||
Direction,
|
Direction,
|
||||||
} from './interface';
|
} from './interface';
|
||||||
|
|
||||||
|
import type { DraggableConfig } from './Tree';
|
||||||
|
|
||||||
export type NodeMouseEventParams = {
|
export type NodeMouseEventParams = {
|
||||||
event: MouseEvent;
|
event: MouseEvent;
|
||||||
node: EventDataNode;
|
node: EventDataNode;
|
||||||
};
|
};
|
||||||
export type NodeDragEventParams = {
|
export type NodeDragEventParams = {
|
||||||
event: MouseEvent;
|
event: DragEvent;
|
||||||
node: EventDataNode;
|
node: EventDataNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NodeMouseEventHandler = (e: MouseEvent, node: EventDataNode) => void;
|
export type NodeMouseEventHandler = (e: MouseEvent, node: EventDataNode) => void;
|
||||||
export type NodeDragEventHandler = (
|
export type NodeDragEventHandler = (
|
||||||
e: MouseEvent,
|
e: DragEvent,
|
||||||
node: DragNodeEvent,
|
node: DragNodeEvent,
|
||||||
outsideTree?: boolean,
|
outsideTree?: boolean,
|
||||||
) => void;
|
) => void;
|
||||||
|
@ -38,12 +39,13 @@ export interface TreeContextProps {
|
||||||
showIcon: boolean;
|
showIcon: boolean;
|
||||||
icon: IconType;
|
icon: IconType;
|
||||||
switcherIcon: IconType;
|
switcherIcon: IconType;
|
||||||
draggable: ((node: DataNode) => boolean) | boolean;
|
draggable: DraggableConfig;
|
||||||
|
draggingNodeKey?: Key;
|
||||||
checkable: boolean;
|
checkable: boolean;
|
||||||
customCheckable: () => any;
|
customCheckable: () => any;
|
||||||
checkStrictly: boolean;
|
checkStrictly: boolean;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
keyEntities: Record<Key, DataEntity>;
|
keyEntities: Record<Key, DataEntity<any>>;
|
||||||
// for details see comment in Tree.state (Tree.tsx)
|
// for details see comment in Tree.state (Tree.tsx)
|
||||||
dropLevelOffset?: number;
|
dropLevelOffset?: number;
|
||||||
dropContainerKey: Key | null;
|
dropContainerKey: Key | null;
|
||||||
|
@ -79,8 +81,8 @@ export interface TreeContextProps {
|
||||||
onNodeDragEnd: NodeDragEventHandler;
|
onNodeDragEnd: NodeDragEventHandler;
|
||||||
onNodeDrop: NodeDragEventHandler;
|
onNodeDrop: NodeDragEventHandler;
|
||||||
slots: {
|
slots: {
|
||||||
title?: (data: DataNode) => any;
|
title?: (data: any) => any;
|
||||||
titleRender?: (data: DataNode) => any;
|
titleRender?: (data: any) => any;
|
||||||
[key: string]: ((...args: any[]) => any) | undefined;
|
[key: string]: ((...args: any[]) => any) | undefined;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// base rc-tree 5.0.1
|
// base rc-tree 5.3.7
|
||||||
import type { TreeProps, TreeNodeProps } from './props';
|
import type { TreeProps, TreeNodeProps } from './props';
|
||||||
import Tree from './Tree';
|
import Tree from './Tree';
|
||||||
import TreeNode from './TreeNode';
|
import TreeNode from './TreeNode';
|
||||||
|
import type { BasicDataNode } from './interface';
|
||||||
export { TreeNode };
|
export { TreeNode };
|
||||||
export type { TreeProps, TreeNodeProps };
|
export type { TreeProps, TreeNodeProps, BasicDataNode };
|
||||||
export default Tree;
|
export default Tree;
|
||||||
|
|
|
@ -2,15 +2,13 @@ import type { CSSProperties, VNode } from 'vue';
|
||||||
import type { TreeNodeProps } from './props';
|
import type { TreeNodeProps } from './props';
|
||||||
export type { ScrollTo } from '../vc-virtual-list/List';
|
export type { ScrollTo } from '../vc-virtual-list/List';
|
||||||
|
|
||||||
export interface DataNode {
|
/** For fieldNames, we provides a abstract interface */
|
||||||
|
export interface BasicDataNode {
|
||||||
checkable?: boolean;
|
checkable?: boolean;
|
||||||
children?: DataNode[];
|
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
disableCheckbox?: boolean;
|
disableCheckbox?: boolean;
|
||||||
icon?: IconType;
|
icon?: IconType;
|
||||||
isLeaf?: boolean;
|
isLeaf?: boolean;
|
||||||
key: string | number;
|
|
||||||
title?: any;
|
|
||||||
selectable?: boolean;
|
selectable?: boolean;
|
||||||
switcherIcon?: IconType;
|
switcherIcon?: IconType;
|
||||||
|
|
||||||
|
@ -21,6 +19,12 @@ export interface DataNode {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DataNode extends BasicDataNode {
|
||||||
|
children?: DataNode[];
|
||||||
|
key: string | number;
|
||||||
|
title?: any;
|
||||||
|
}
|
||||||
|
|
||||||
export interface EventDataNode extends DataNode {
|
export interface EventDataNode extends DataNode {
|
||||||
expanded?: boolean;
|
expanded?: boolean;
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
|
@ -60,10 +64,12 @@ export interface Entity {
|
||||||
children?: Entity[];
|
children?: Entity[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataEntity extends Omit<Entity, 'node' | 'parent' | 'children'> {
|
export interface DataEntity<TreeDataType extends BasicDataNode = DataNode>
|
||||||
node: DataNode;
|
extends Omit<Entity, 'node' | 'parent' | 'children'> {
|
||||||
parent?: DataEntity;
|
node: TreeDataType;
|
||||||
children?: DataEntity[];
|
nodes: TreeDataType[];
|
||||||
|
parent?: DataEntity<TreeDataType>;
|
||||||
|
children?: DataEntity<TreeDataType>[];
|
||||||
level: number;
|
level: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +92,8 @@ export type Direction = 'ltr' | 'rtl' | undefined;
|
||||||
|
|
||||||
export interface FieldNames {
|
export interface FieldNames {
|
||||||
title?: string;
|
title?: string;
|
||||||
|
/** @private Internal usage for `vc-tree-select`, safe to remove if no need */
|
||||||
|
_title?: string[];
|
||||||
key?: string;
|
key?: string;
|
||||||
children?: string;
|
children?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type { ExtractPropTypes, PropType } from 'vue';
|
import type { ExtractPropTypes, PropType } from 'vue';
|
||||||
|
import type { BasicDataNode } from '.';
|
||||||
import type { EventHandler } from '../_util/EventInterface';
|
import type { EventHandler } from '../_util/EventInterface';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import type {
|
import type {
|
||||||
|
@ -10,10 +11,10 @@ import type {
|
||||||
DataNode,
|
DataNode,
|
||||||
Key,
|
Key,
|
||||||
FlattenNode,
|
FlattenNode,
|
||||||
DataEntity,
|
|
||||||
EventDataNode,
|
EventDataNode,
|
||||||
Direction,
|
Direction,
|
||||||
FieldNames,
|
FieldNames,
|
||||||
|
DataEntity,
|
||||||
} from './interface';
|
} from './interface';
|
||||||
|
|
||||||
export interface CheckInfo {
|
export interface CheckInfo {
|
||||||
|
@ -83,7 +84,7 @@ export const nodeListProps = {
|
||||||
loadedKeys: { type: Array as PropType<Key[]> },
|
loadedKeys: { type: Array as PropType<Key[]> },
|
||||||
loadingKeys: { type: Array as PropType<Key[]> },
|
loadingKeys: { type: Array as PropType<Key[]> },
|
||||||
halfCheckedKeys: { type: Array as PropType<Key[]> },
|
halfCheckedKeys: { type: Array as PropType<Key[]> },
|
||||||
keyEntities: { type: Object as PropType<Record<Key, DataEntity>> },
|
keyEntities: { type: Object as PropType<Record<Key, DataEntity<DataNode>>> },
|
||||||
|
|
||||||
dragging: { type: Boolean as PropType<boolean> },
|
dragging: { type: Boolean as PropType<boolean> },
|
||||||
dragOverNodeKey: { type: [String, Number] as PropType<Key> },
|
dragOverNodeKey: { type: [String, Number] as PropType<Key> },
|
||||||
|
@ -106,8 +107,17 @@ export const nodeListProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NodeListProps = Partial<ExtractPropTypes<typeof nodeListProps>>;
|
export type NodeListProps = Partial<ExtractPropTypes<typeof nodeListProps>>;
|
||||||
export type AllowDrop = (options: { dropNode: DataNode; dropPosition: -1 | 0 | 1 }) => boolean;
|
|
||||||
|
|
||||||
|
export interface AllowDropOptions<TreeDataType extends BasicDataNode = DataNode> {
|
||||||
|
dragNode: EventDataNode;
|
||||||
|
dropNode: TreeDataType;
|
||||||
|
dropPosition: -1 | 0 | 1;
|
||||||
|
}
|
||||||
|
export type AllowDrop<TreeDataType extends BasicDataNode = DataNode> = (
|
||||||
|
options: AllowDropOptions<TreeDataType>,
|
||||||
|
) => boolean;
|
||||||
|
|
||||||
|
export type DraggableFn = (node: DataNode) => boolean;
|
||||||
export const treeProps = () => ({
|
export const treeProps = () => ({
|
||||||
prefixCls: String,
|
prefixCls: String,
|
||||||
focusable: { type: Boolean, default: undefined },
|
focusable: { type: Boolean, default: undefined },
|
||||||
|
@ -123,7 +133,7 @@ export const treeProps = () => ({
|
||||||
multiple: { type: Boolean, default: undefined },
|
multiple: { type: Boolean, default: undefined },
|
||||||
checkable: { type: Boolean, default: undefined },
|
checkable: { type: Boolean, default: undefined },
|
||||||
checkStrictly: { type: Boolean, default: undefined },
|
checkStrictly: { type: Boolean, default: undefined },
|
||||||
draggable: { type: [Function, Boolean] as PropType<((node: DataNode) => boolean) | boolean> },
|
draggable: { type: [Function, Boolean] as PropType<DraggableFn | boolean> },
|
||||||
defaultExpandParent: { type: Boolean, default: undefined },
|
defaultExpandParent: { type: Boolean, default: undefined },
|
||||||
autoExpandParent: { type: Boolean, default: undefined },
|
autoExpandParent: { type: Boolean, default: undefined },
|
||||||
defaultExpandAll: { type: Boolean, default: undefined },
|
defaultExpandAll: { type: Boolean, default: undefined },
|
||||||
|
|
|
@ -12,11 +12,13 @@ import type {
|
||||||
FlattenNode,
|
FlattenNode,
|
||||||
Direction,
|
Direction,
|
||||||
DragNodeEvent,
|
DragNodeEvent,
|
||||||
|
BasicDataNode,
|
||||||
} from './interface';
|
} from './interface';
|
||||||
import { warning } from '../vc-util/warning';
|
import { warning } from '../vc-util/warning';
|
||||||
import type { AllowDrop, TreeNodeProps, TreeProps } from './props';
|
import type { AllowDrop, TreeNodeProps, TreeProps } from './props';
|
||||||
|
|
||||||
export function arrDel(list: Key[], value: Key) {
|
export function arrDel(list: Key[], value: Key) {
|
||||||
|
if (!list) return [];
|
||||||
const clone = list.slice();
|
const clone = list.slice();
|
||||||
const index = clone.indexOf(value);
|
const index = clone.indexOf(value);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
|
@ -26,7 +28,7 @@ export function arrDel(list: Key[], value: Key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function arrAdd(list: Key[], value: Key) {
|
export function arrAdd(list: Key[], value: Key) {
|
||||||
const clone = list.slice();
|
const clone = (list || []).slice();
|
||||||
if (clone.indexOf(value) === -1) {
|
if (clone.indexOf(value) === -1) {
|
||||||
clone.push(value);
|
clone.push(value);
|
||||||
}
|
}
|
||||||
|
@ -45,13 +47,16 @@ export function isTreeNode(node: NodeElement) {
|
||||||
return node && node.type && (node.type as any).isTreeNode;
|
return node && node.type && (node.type as any).isTreeNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDragChildrenKeys(dragNodeKey: Key, keyEntities: Record<Key, DataEntity>): Key[] {
|
export function getDragChildrenKeys<TreeDataType extends BasicDataNode = DataNode>(
|
||||||
|
dragNodeKey: Key,
|
||||||
|
keyEntities: Record<Key, DataEntity<TreeDataType>>,
|
||||||
|
): Key[] {
|
||||||
// not contains self
|
// not contains self
|
||||||
// self for left or right drag
|
// self for left or right drag
|
||||||
const dragChildrenKeys = [];
|
const dragChildrenKeys = [];
|
||||||
|
|
||||||
const entity = keyEntities[dragNodeKey];
|
const entity = keyEntities[dragNodeKey];
|
||||||
function dig(list: DataEntity[] = []) {
|
function dig(list: DataEntity<TreeDataType>[] = []) {
|
||||||
list.forEach(({ key, children }) => {
|
list.forEach(({ key, children }) => {
|
||||||
dragChildrenKeys.push(key);
|
dragChildrenKeys.push(key);
|
||||||
dig(children);
|
dig(children);
|
||||||
|
@ -63,7 +68,9 @@ export function getDragChildrenKeys(dragNodeKey: Key, keyEntities: Record<Key, D
|
||||||
return dragChildrenKeys;
|
return dragChildrenKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isLastChild(treeNodeEntity: DataEntity) {
|
export function isLastChild<TreeDataType extends BasicDataNode = DataNode>(
|
||||||
|
treeNodeEntity: DataEntity<TreeDataType>,
|
||||||
|
) {
|
||||||
if (treeNodeEntity.parent) {
|
if (treeNodeEntity.parent) {
|
||||||
const posArr = posToArr(treeNodeEntity.pos);
|
const posArr = posToArr(treeNodeEntity.pos);
|
||||||
return Number(posArr[posArr.length - 1]) === treeNodeEntity.parent.children.length - 1;
|
return Number(posArr[posArr.length - 1]) === treeNodeEntity.parent.children.length - 1;
|
||||||
|
@ -71,24 +78,26 @@ export function isLastChild(treeNodeEntity: DataEntity) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isFirstChild(treeNodeEntity: DataEntity) {
|
export function isFirstChild<TreeDataType extends BasicDataNode = DataNode>(
|
||||||
|
treeNodeEntity: DataEntity<TreeDataType>,
|
||||||
|
) {
|
||||||
const posArr = posToArr(treeNodeEntity.pos);
|
const posArr = posToArr(treeNodeEntity.pos);
|
||||||
return Number(posArr[posArr.length - 1]) === 0;
|
return Number(posArr[posArr.length - 1]) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only used when drag, not affect SSR.
|
// Only used when drag, not affect SSR.
|
||||||
export function calcDropPosition(
|
export function calcDropPosition<TreeDataType extends BasicDataNode = DataNode>(
|
||||||
event: MouseEvent,
|
event: MouseEvent,
|
||||||
_dragNode: DragNodeEvent,
|
dragNode: DragNodeEvent,
|
||||||
targetNode: DragNodeEvent,
|
targetNode: DragNodeEvent,
|
||||||
indent: number,
|
indent: number,
|
||||||
startMousePosition: {
|
startMousePosition: {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
},
|
},
|
||||||
allowDrop: AllowDrop,
|
allowDrop: AllowDrop<TreeDataType>,
|
||||||
flattenedNodes: FlattenNode[],
|
flattenedNodes: FlattenNode[],
|
||||||
keyEntities: Record<Key, DataEntity>,
|
keyEntities: Record<Key, DataEntity<TreeDataType>>,
|
||||||
expandKeys: Key[],
|
expandKeys: Key[],
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
): {
|
): {
|
||||||
|
@ -108,7 +117,7 @@ export function calcDropPosition(
|
||||||
const rawDropLevelOffset = (horizontalMouseOffset - 12) / indent;
|
const rawDropLevelOffset = (horizontalMouseOffset - 12) / indent;
|
||||||
|
|
||||||
// find abstract drop node by horizontal offset
|
// find abstract drop node by horizontal offset
|
||||||
let abstractDropNodeEntity: DataEntity = keyEntities[targetNode.eventKey];
|
let abstractDropNodeEntity: DataEntity<TreeDataType> = keyEntities[targetNode.eventKey];
|
||||||
|
|
||||||
if (clientY < top + height / 2) {
|
if (clientY < top + height / 2) {
|
||||||
// first half, set abstract drop node to previous node
|
// first half, set abstract drop node to previous node
|
||||||
|
@ -139,7 +148,7 @@ export function calcDropPosition(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const abstractDragDataNode = dragNode.eventData;
|
||||||
const abstractDropDataNode = abstractDropNodeEntity.node;
|
const abstractDropDataNode = abstractDropNodeEntity.node;
|
||||||
let dropAllowed = true;
|
let dropAllowed = true;
|
||||||
if (
|
if (
|
||||||
|
@ -147,6 +156,7 @@ export function calcDropPosition(
|
||||||
abstractDropNodeEntity.level === 0 &&
|
abstractDropNodeEntity.level === 0 &&
|
||||||
clientY < top + height / 2 &&
|
clientY < top + height / 2 &&
|
||||||
allowDrop({
|
allowDrop({
|
||||||
|
dragNode: abstractDragDataNode,
|
||||||
dropNode: abstractDropDataNode,
|
dropNode: abstractDropDataNode,
|
||||||
dropPosition: -1,
|
dropPosition: -1,
|
||||||
}) &&
|
}) &&
|
||||||
|
@ -162,6 +172,7 @@ export function calcDropPosition(
|
||||||
// only allow drop inside
|
// only allow drop inside
|
||||||
if (
|
if (
|
||||||
allowDrop({
|
allowDrop({
|
||||||
|
dragNode: abstractDragDataNode,
|
||||||
dropNode: abstractDropDataNode,
|
dropNode: abstractDropDataNode,
|
||||||
dropPosition: 0,
|
dropPosition: 0,
|
||||||
})
|
})
|
||||||
|
@ -178,6 +189,7 @@ export function calcDropPosition(
|
||||||
// 2. do not allow drop
|
// 2. do not allow drop
|
||||||
if (
|
if (
|
||||||
allowDrop({
|
allowDrop({
|
||||||
|
dragNode: abstractDragDataNode,
|
||||||
dropNode: abstractDropDataNode,
|
dropNode: abstractDropDataNode,
|
||||||
dropPosition: 1,
|
dropPosition: 1,
|
||||||
})
|
})
|
||||||
|
@ -196,6 +208,7 @@ export function calcDropPosition(
|
||||||
// 3. do not allow drop
|
// 3. do not allow drop
|
||||||
if (
|
if (
|
||||||
allowDrop({
|
allowDrop({
|
||||||
|
dragNode: abstractDragDataNode,
|
||||||
dropNode: abstractDropDataNode,
|
dropNode: abstractDropDataNode,
|
||||||
dropPosition: 0,
|
dropPosition: 0,
|
||||||
})
|
})
|
||||||
|
@ -203,6 +216,7 @@ export function calcDropPosition(
|
||||||
dropPosition = 0;
|
dropPosition = 0;
|
||||||
} else if (
|
} else if (
|
||||||
allowDrop({
|
allowDrop({
|
||||||
|
dragNode: abstractDragDataNode,
|
||||||
dropNode: abstractDropDataNode,
|
dropNode: abstractDropDataNode,
|
||||||
dropPosition: 1,
|
dropPosition: 1,
|
||||||
})
|
})
|
||||||
|
@ -220,6 +234,7 @@ export function calcDropPosition(
|
||||||
// 2. do not allow drop
|
// 2. do not allow drop
|
||||||
if (
|
if (
|
||||||
allowDrop({
|
allowDrop({
|
||||||
|
dragNode: abstractDragDataNode,
|
||||||
dropNode: abstractDropDataNode,
|
dropNode: abstractDropDataNode,
|
||||||
dropPosition: 1,
|
dropPosition: 1,
|
||||||
})
|
})
|
||||||
|
@ -336,17 +351,3 @@ export function conductExpandParent(keyList: Key[], keyEntities: Record<Key, Dat
|
||||||
|
|
||||||
return [...expandedKeys];
|
return [...expandedKeys];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns only the data- and aria- key/value pairs
|
|
||||||
*/
|
|
||||||
export function getDataAndAria(props: Partial<TreeProps | TreeNodeProps>) {
|
|
||||||
const omitProps: Record<string, string> = {};
|
|
||||||
Object.keys(props).forEach(key => {
|
|
||||||
if (key.startsWith('data-') || key.startsWith('aria-')) {
|
|
||||||
omitProps[key] = props[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return omitProps;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { warning } from '../../vc-util/warning';
|
import { warning } from '../../vc-util/warning';
|
||||||
import type { Key, DataEntity, DataNode, GetCheckDisabled } from '../interface';
|
import type { Key, DataEntity, DataNode, GetCheckDisabled, BasicDataNode } from '../interface';
|
||||||
|
|
||||||
interface ConductReturnType {
|
interface ConductReturnType {
|
||||||
checkedKeys: Key[];
|
checkedKeys: Key[];
|
||||||
|
@ -16,17 +16,17 @@ function removeFromCheckedKeys(halfCheckedKeys: Set<Key>, checkedKeys: Set<Key>)
|
||||||
return filteredKeys;
|
return filteredKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isCheckDisabled(node: DataNode) {
|
export function isCheckDisabled<TreeDataType>(node: TreeDataType) {
|
||||||
const { disabled, disableCheckbox, checkable } = (node || {}) as DataNode;
|
const { disabled, disableCheckbox, checkable } = (node || {}) as DataNode;
|
||||||
return !!(disabled || disableCheckbox) || checkable === false;
|
return !!(disabled || disableCheckbox) || checkable === false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill miss keys
|
// Fill miss keys
|
||||||
function fillConductCheck(
|
function fillConductCheck<TreeDataType extends BasicDataNode = DataNode>(
|
||||||
keys: Set<Key>,
|
keys: Set<Key>,
|
||||||
levelEntities: Map<number, Set<DataEntity>>,
|
levelEntities: Map<number, Set<DataEntity<TreeDataType>>>,
|
||||||
maxLevel: number,
|
maxLevel: number,
|
||||||
syntheticGetCheckDisabled: GetCheckDisabled<DataNode>,
|
syntheticGetCheckDisabled: GetCheckDisabled<TreeDataType>,
|
||||||
): ConductReturnType {
|
): ConductReturnType {
|
||||||
const checkedKeys = new Set<Key>(keys);
|
const checkedKeys = new Set<Key>(keys);
|
||||||
const halfCheckedKeys = new Set<Key>();
|
const halfCheckedKeys = new Set<Key>();
|
||||||
|
@ -98,12 +98,12 @@ function fillConductCheck(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove useless key
|
// Remove useless key
|
||||||
function cleanConductCheck(
|
function cleanConductCheck<TreeDataType extends BasicDataNode = DataNode>(
|
||||||
keys: Set<Key>,
|
keys: Set<Key>,
|
||||||
halfKeys: Key[],
|
halfKeys: Key[],
|
||||||
levelEntities: Map<number, Set<DataEntity>>,
|
levelEntities: Map<number, Set<DataEntity<TreeDataType>>>,
|
||||||
maxLevel: number,
|
maxLevel: number,
|
||||||
syntheticGetCheckDisabled: GetCheckDisabled<DataNode>,
|
syntheticGetCheckDisabled: GetCheckDisabled<TreeDataType>,
|
||||||
): ConductReturnType {
|
): ConductReturnType {
|
||||||
const checkedKeys = new Set<Key>(keys);
|
const checkedKeys = new Set<Key>(keys);
|
||||||
let halfCheckedKeys = new Set<Key>(halfKeys);
|
let halfCheckedKeys = new Set<Key>(halfKeys);
|
||||||
|
@ -182,15 +182,15 @@ function cleanConductCheck(
|
||||||
* @param keyEntities key - dataEntity map
|
* @param keyEntities key - dataEntity map
|
||||||
* @param mode `fill` to fill missing key, `clean` to remove useless key
|
* @param mode `fill` to fill missing key, `clean` to remove useless key
|
||||||
*/
|
*/
|
||||||
export function conductCheck(
|
export function conductCheck<TreeDataType extends BasicDataNode = DataNode>(
|
||||||
keyList: Key[],
|
keyList: Key[],
|
||||||
checked: true | { checked: false; halfCheckedKeys: Key[] },
|
checked: true | { checked: false; halfCheckedKeys: Key[] },
|
||||||
keyEntities: Record<Key, DataEntity>,
|
keyEntities: Record<Key, DataEntity<TreeDataType>>,
|
||||||
getCheckDisabled?: GetCheckDisabled<DataNode>,
|
getCheckDisabled?: GetCheckDisabled<TreeDataType>,
|
||||||
): ConductReturnType {
|
): ConductReturnType {
|
||||||
const warningMissKeys: Key[] = [];
|
const warningMissKeys: Key[] = [];
|
||||||
|
|
||||||
let syntheticGetCheckDisabled: GetCheckDisabled<DataNode>;
|
let syntheticGetCheckDisabled: GetCheckDisabled<TreeDataType>;
|
||||||
if (getCheckDisabled) {
|
if (getCheckDisabled) {
|
||||||
syntheticGetCheckDisabled = getCheckDisabled;
|
syntheticGetCheckDisabled = getCheckDisabled;
|
||||||
} else {
|
} else {
|
||||||
|
@ -208,7 +208,7 @@ export function conductCheck(
|
||||||
return hasEntity;
|
return hasEntity;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
const levelEntities = new Map<number, Set<DataEntity>>();
|
const levelEntities = new Map<number, Set<DataEntity<TreeDataType>>>();
|
||||||
let maxLevel = 0;
|
let maxLevel = 0;
|
||||||
|
|
||||||
// Convert entities by level for calculation
|
// Convert entities by level for calculation
|
||||||
|
@ -216,7 +216,7 @@ export function conductCheck(
|
||||||
const entity = keyEntities[key];
|
const entity = keyEntities[key];
|
||||||
const { level } = entity;
|
const { level } = entity;
|
||||||
|
|
||||||
let levelSet: Set<DataEntity> = levelEntities.get(level);
|
let levelSet: Set<DataEntity<TreeDataType>> = levelEntities.get(level);
|
||||||
if (!levelSet) {
|
if (!levelSet) {
|
||||||
levelSet = new Set();
|
levelSet = new Set();
|
||||||
levelEntities.set(level, levelSet);
|
levelEntities.set(level, levelSet);
|
||||||
|
@ -237,7 +237,12 @@ export function conductCheck(
|
||||||
|
|
||||||
let result: ConductReturnType;
|
let result: ConductReturnType;
|
||||||
if (checked === true) {
|
if (checked === true) {
|
||||||
result = fillConductCheck(keys, levelEntities, maxLevel, syntheticGetCheckDisabled);
|
result = fillConductCheck<TreeDataType>(
|
||||||
|
keys,
|
||||||
|
levelEntities,
|
||||||
|
maxLevel,
|
||||||
|
syntheticGetCheckDisabled,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
result = cleanConductCheck(
|
result = cleanConductCheck(
|
||||||
keys,
|
keys,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import type {
|
||||||
EventDataNode,
|
EventDataNode,
|
||||||
GetKey,
|
GetKey,
|
||||||
FieldNames,
|
FieldNames,
|
||||||
|
BasicDataNode,
|
||||||
} from '../interface';
|
} from '../interface';
|
||||||
import { getPosition, isTreeNode } from '../util';
|
import { getPosition, isTreeNode } from '../util';
|
||||||
import { warning } from '../../vc-util/warning';
|
import { warning } from '../../vc-util/warning';
|
||||||
|
@ -23,11 +24,13 @@ export function getKey(key: Key, pos: string) {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fillFieldNames(fieldNames?: FieldNames) {
|
export function fillFieldNames(fieldNames?: FieldNames): Required<FieldNames> {
|
||||||
const { title, key, children } = fieldNames || {};
|
const { title, _title, key, children } = fieldNames || {};
|
||||||
|
const mergedTitle = title || 'title';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: title || 'title',
|
title: mergedTitle,
|
||||||
|
_title: _title || [mergedTitle],
|
||||||
key: key || 'key',
|
key: key || 'key',
|
||||||
children: children || 'children',
|
children: children || 'children',
|
||||||
};
|
};
|
||||||
|
@ -129,7 +132,11 @@ export function flattenTreeData(
|
||||||
expandedKeys: Key[] | true,
|
expandedKeys: Key[] | true,
|
||||||
fieldNames: FieldNames,
|
fieldNames: FieldNames,
|
||||||
): FlattenNode[] {
|
): FlattenNode[] {
|
||||||
const { title: fieldTitle, key: fieldKey, children: fieldChildren } = fillFieldNames(fieldNames);
|
const {
|
||||||
|
_title: fieldTitles,
|
||||||
|
key: fieldKey,
|
||||||
|
children: fieldChildren,
|
||||||
|
} = fillFieldNames(fieldNames);
|
||||||
|
|
||||||
const expandedKeySet = new Set(expandedKeys === true ? [] : expandedKeys);
|
const expandedKeySet = new Set(expandedKeys === true ? [] : expandedKeys);
|
||||||
const flattenList: FlattenNode[] = [];
|
const flattenList: FlattenNode[] = [];
|
||||||
|
@ -139,10 +146,19 @@ export function flattenTreeData(
|
||||||
const pos: string = getPosition(parent ? parent.pos : '0', index);
|
const pos: string = getPosition(parent ? parent.pos : '0', index);
|
||||||
const mergedKey = getKey(treeNode[fieldKey], pos);
|
const mergedKey = getKey(treeNode[fieldKey], pos);
|
||||||
|
|
||||||
|
// Pick matched title in field title list
|
||||||
|
let mergedTitle: any;
|
||||||
|
for (let i = 0; i < fieldTitles.length; i += 1) {
|
||||||
|
const fieldTitle = fieldTitles[i];
|
||||||
|
if (treeNode[fieldTitle] !== undefined) {
|
||||||
|
mergedTitle = treeNode[fieldTitle];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Add FlattenDataNode into list
|
// Add FlattenDataNode into list
|
||||||
const flattenNode: FlattenNode = {
|
const flattenNode: FlattenNode = {
|
||||||
...omit(treeNode, [fieldTitle, fieldKey, fieldChildren] as any),
|
...omit(treeNode, [...fieldTitles, fieldKey, fieldChildren] as any),
|
||||||
title: treeNode[fieldTitle],
|
title: mergedTitle,
|
||||||
key: mergedKey,
|
key: mergedKey,
|
||||||
parent,
|
parent,
|
||||||
pos,
|
pos,
|
||||||
|
@ -191,6 +207,7 @@ export function traverseDataNodes(
|
||||||
key: Key;
|
key: Key;
|
||||||
parentPos: string | number;
|
parentPos: string | number;
|
||||||
level: number;
|
level: number;
|
||||||
|
nodes: DataNode[];
|
||||||
}) => void,
|
}) => void,
|
||||||
// To avoid too many params, let use config instead of origin param
|
// To avoid too many params, let use config instead of origin param
|
||||||
config?: TraverseDataNodesConfig | string,
|
config?: TraverseDataNodesConfig | string,
|
||||||
|
@ -227,9 +244,11 @@ export function traverseDataNodes(
|
||||||
node: DataNode,
|
node: DataNode,
|
||||||
index?: number,
|
index?: number,
|
||||||
parent?: { node: DataNode; pos: string; level: number },
|
parent?: { node: DataNode; pos: string; level: number },
|
||||||
|
pathNodes?: DataNode[],
|
||||||
) {
|
) {
|
||||||
const children = node ? node[mergeChildrenPropName] : dataNodes;
|
const children = node ? node[mergeChildrenPropName] : dataNodes;
|
||||||
const pos = node ? getPosition(parent.pos, index) : '0';
|
const pos = node ? getPosition(parent.pos, index) : '0';
|
||||||
|
const connectNodes = node ? [...pathNodes, node] : [];
|
||||||
|
|
||||||
// Process node if is not root
|
// Process node if is not root
|
||||||
if (node) {
|
if (node) {
|
||||||
|
@ -241,6 +260,7 @@ export function traverseDataNodes(
|
||||||
key,
|
key,
|
||||||
parentPos: parent.node ? parent.pos : null,
|
parentPos: parent.node ? parent.pos : null,
|
||||||
level: parent.level + 1,
|
level: parent.level + 1,
|
||||||
|
nodes: connectNodes,
|
||||||
};
|
};
|
||||||
|
|
||||||
callback(data);
|
callback(data);
|
||||||
|
@ -249,11 +269,16 @@ export function traverseDataNodes(
|
||||||
// Process children node
|
// Process children node
|
||||||
if (children) {
|
if (children) {
|
||||||
children.forEach((subNode, subIndex) => {
|
children.forEach((subNode, subIndex) => {
|
||||||
processNode(subNode, subIndex, {
|
processNode(
|
||||||
|
subNode,
|
||||||
|
subIndex,
|
||||||
|
{
|
||||||
node,
|
node,
|
||||||
pos,
|
pos,
|
||||||
level: parent ? parent.level + 1 : -1,
|
level: parent ? parent.level + 1 : -1,
|
||||||
});
|
},
|
||||||
|
connectNodes,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,8 +331,8 @@ export function convertDataToEntities(
|
||||||
traverseDataNodes(
|
traverseDataNodes(
|
||||||
dataNodes,
|
dataNodes,
|
||||||
item => {
|
item => {
|
||||||
const { node, index, pos, key, parentPos, level } = item;
|
const { node, index, pos, key, parentPos, level, nodes } = item;
|
||||||
const entity: DataEntity = { node, index, key, pos, level };
|
const entity: DataEntity = { node, nodes, index, key, pos, level };
|
||||||
|
|
||||||
const mergedKey = getKey(key, pos);
|
const mergedKey = getKey(key, pos);
|
||||||
|
|
||||||
|
@ -335,7 +360,7 @@ export function convertDataToEntities(
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TreeNodeRequiredProps {
|
export interface TreeNodeRequiredProps<TreeDataType extends BasicDataNode = DataNode> {
|
||||||
expandedKeys: Key[];
|
expandedKeys: Key[];
|
||||||
selectedKeys: Key[];
|
selectedKeys: Key[];
|
||||||
loadedKeys: Key[];
|
loadedKeys: Key[];
|
||||||
|
@ -344,13 +369,13 @@ export interface TreeNodeRequiredProps {
|
||||||
halfCheckedKeys: Key[];
|
halfCheckedKeys: Key[];
|
||||||
dragOverNodeKey: Key;
|
dragOverNodeKey: Key;
|
||||||
dropPosition: number;
|
dropPosition: number;
|
||||||
keyEntities: Record<Key, DataEntity>;
|
keyEntities: Record<Key, DataEntity<TreeDataType>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get TreeNode props with Tree props.
|
* Get TreeNode props with Tree props.
|
||||||
*/
|
*/
|
||||||
export function getTreeNodeProps(
|
export function getTreeNodeProps<TreeDataType extends BasicDataNode = DataNode>(
|
||||||
key: Key,
|
key: Key,
|
||||||
{
|
{
|
||||||
expandedKeys,
|
expandedKeys,
|
||||||
|
@ -362,7 +387,7 @@ export function getTreeNodeProps(
|
||||||
dragOverNodeKey,
|
dragOverNodeKey,
|
||||||
dropPosition,
|
dropPosition,
|
||||||
keyEntities,
|
keyEntities,
|
||||||
}: TreeNodeRequiredProps,
|
}: TreeNodeRequiredProps<TreeDataType>,
|
||||||
) {
|
) {
|
||||||
const entity = keyEntities[key];
|
const entity = keyEntities[key];
|
||||||
|
|
||||||
|
@ -418,6 +443,7 @@ export function convertNodePropsToEventData(props: TreeNodeProps): EventDataNode
|
||||||
pos,
|
pos,
|
||||||
active,
|
active,
|
||||||
eventKey,
|
eventKey,
|
||||||
|
key: eventKey,
|
||||||
};
|
};
|
||||||
if (!('props' in eventData)) {
|
if (!('props' in eventData)) {
|
||||||
Object.defineProperty(eventData, 'props', {
|
Object.defineProperty(eventData, 'props', {
|
||||||
|
|
|
@ -96,6 +96,7 @@ const List = defineComponent({
|
||||||
onScroll: PropTypes.func,
|
onScroll: PropTypes.func,
|
||||||
onMousedown: PropTypes.func,
|
onMousedown: PropTypes.func,
|
||||||
onMouseenter: PropTypes.func,
|
onMouseenter: PropTypes.func,
|
||||||
|
onVisibleChange: Function as PropType<(visibleList: any[], fullList: any[]) => void>,
|
||||||
},
|
},
|
||||||
setup(props, { expose }) {
|
setup(props, { expose }) {
|
||||||
// ================================= MISC =================================
|
// ================================= MISC =================================
|
||||||
|
@ -400,6 +401,20 @@ const List = defineComponent({
|
||||||
return cs;
|
return cs;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ================================ Effect ================================
|
||||||
|
/** We need told outside that some list not rendered */
|
||||||
|
watch(
|
||||||
|
[() => calRes.start, () => calRes.end, mergedData],
|
||||||
|
() => {
|
||||||
|
if (props.onVisibleChange) {
|
||||||
|
const renderList = mergedData.value.slice(calRes.start, calRes.end + 1);
|
||||||
|
|
||||||
|
props.onVisibleChange(renderList, mergedData.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ flush: 'post' },
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
mergedData,
|
mergedData,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// base rc-virtual-list 3.4.2
|
||||||
import List from './List';
|
import List from './List';
|
||||||
|
|
||||||
export default List;
|
export default List;
|
||||||
|
|
Loading…
Reference in New Issue