refactor:tree (#6276)
parent
9f53d53cb8
commit
895b43338d
|
@ -42,7 +42,7 @@ import './cascader/style';
|
||||||
// import './timeline/style';
|
// import './timeline/style';
|
||||||
// import './input-number/style';
|
// import './input-number/style';
|
||||||
// import './transfer/style';
|
// import './transfer/style';
|
||||||
import './tree/style';
|
// import './tree/style';
|
||||||
// import './upload/style';
|
// import './upload/style';
|
||||||
// import './layout/style';
|
// import './layout/style';
|
||||||
// import './anchor/style';
|
// import './anchor/style';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ExtractPropTypes, PropType } from 'vue';
|
import type { ExtractPropTypes } from 'vue';
|
||||||
import { nextTick, onUpdated, ref, watch, defineComponent, computed } from 'vue';
|
import { nextTick, onUpdated, ref, watch, defineComponent, computed } from 'vue';
|
||||||
import debounce from 'lodash-es/debounce';
|
import debounce from 'lodash-es/debounce';
|
||||||
import FolderOpenOutlined from '@ant-design/icons-vue/FolderOpenOutlined';
|
import FolderOpenOutlined from '@ant-design/icons-vue/FolderOpenOutlined';
|
||||||
|
@ -18,12 +18,13 @@ import { conductExpandParent } from '../vc-tree/util';
|
||||||
import { calcRangeKeys, convertDirectoryKeysToNodes } from './utils/dictUtil';
|
import { calcRangeKeys, convertDirectoryKeysToNodes } from './utils/dictUtil';
|
||||||
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||||
import { filterEmpty } from '../_util/props-util';
|
import { filterEmpty } from '../_util/props-util';
|
||||||
|
import { someType } from '../_util/type';
|
||||||
|
|
||||||
export type ExpandAction = false | 'click' | 'doubleclick' | 'dblclick';
|
export type ExpandAction = false | 'click' | 'doubleclick' | 'dblclick';
|
||||||
|
|
||||||
export const directoryTreeProps = () => ({
|
export const directoryTreeProps = () => ({
|
||||||
...treeProps(),
|
...treeProps(),
|
||||||
expandAction: { type: [Boolean, String] as PropType<ExpandAction> },
|
expandAction: someType<ExpandAction>([Boolean, String]),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type DirectoryTreeProps = Partial<ExtractPropTypes<ReturnType<typeof directoryTreeProps>>>;
|
export type DirectoryTreeProps = Partial<ExtractPropTypes<ReturnType<typeof directoryTreeProps>>>;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { PropType, ExtractPropTypes } from 'vue';
|
import type { ExtractPropTypes } from 'vue';
|
||||||
import { watchEffect, ref, defineComponent, computed } from 'vue';
|
import { watchEffect, ref, defineComponent, computed } from 'vue';
|
||||||
import classNames from '../_util/classNames';
|
import classNames from '../_util/classNames';
|
||||||
import VcTree from '../vc-tree';
|
import VcTree from '../vc-tree';
|
||||||
|
@ -15,6 +15,10 @@ import dropIndicatorRender from './utils/dropIndicator';
|
||||||
import devWarning from '../vc-util/devWarning';
|
import devWarning from '../vc-util/devWarning';
|
||||||
import { warning } from '../vc-util/warning';
|
import { warning } from '../vc-util/warning';
|
||||||
import omit from '../_util/omit';
|
import omit from '../_util/omit';
|
||||||
|
import { booleanType, someType, arrayType, functionType, objectType } from '../_util/type';
|
||||||
|
|
||||||
|
// CSSINJS
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
export interface AntdTreeNodeAttribute {
|
export interface AntdTreeNodeAttribute {
|
||||||
eventKey: string;
|
eventKey: string;
|
||||||
|
@ -84,44 +88,39 @@ export const treeProps = () => {
|
||||||
const baseTreeProps = vcTreeProps();
|
const baseTreeProps = vcTreeProps();
|
||||||
return {
|
return {
|
||||||
...baseTreeProps,
|
...baseTreeProps,
|
||||||
showLine: {
|
showLine: someType<boolean | { showLeafIcon: boolean }>([Boolean, Object]),
|
||||||
type: [Boolean, Object] as PropType<boolean | { showLeafIcon: boolean }>,
|
|
||||||
default: undefined,
|
|
||||||
},
|
|
||||||
/** 是否支持多选 */
|
/** 是否支持多选 */
|
||||||
multiple: { type: Boolean, default: undefined },
|
multiple: booleanType(),
|
||||||
/** 是否自动展开父节点 */
|
/** 是否自动展开父节点 */
|
||||||
autoExpandParent: { type: Boolean, default: undefined },
|
autoExpandParent: booleanType(),
|
||||||
/** checkable状态下节点选择完全受控(父子节点选中状态不再关联)*/
|
/** checkable状态下节点选择完全受控(父子节点选中状态不再关联)*/
|
||||||
checkStrictly: { type: Boolean, default: undefined },
|
checkStrictly: booleanType(),
|
||||||
/** 是否支持选中 */
|
/** 是否支持选中 */
|
||||||
checkable: { type: Boolean, default: undefined },
|
checkable: booleanType(),
|
||||||
/** 是否禁用树 */
|
/** 是否禁用树 */
|
||||||
disabled: { type: Boolean, default: undefined },
|
disabled: booleanType(),
|
||||||
/** 默认展开所有树节点 */
|
/** 默认展开所有树节点 */
|
||||||
defaultExpandAll: { type: Boolean, default: undefined },
|
defaultExpandAll: booleanType(),
|
||||||
/** 默认展开对应树节点 */
|
/** 默认展开对应树节点 */
|
||||||
defaultExpandParent: { type: Boolean, default: undefined },
|
defaultExpandParent: booleanType(),
|
||||||
/** 默认展开指定的树节点 */
|
/** 默认展开指定的树节点 */
|
||||||
defaultExpandedKeys: { type: Array as PropType<Key[]> },
|
defaultExpandedKeys: arrayType<Key[]>(),
|
||||||
/** (受控)展开指定的树节点 */
|
/** (受控)展开指定的树节点 */
|
||||||
expandedKeys: { type: Array as PropType<Key[]> },
|
expandedKeys: arrayType<Key[]>(),
|
||||||
/** (受控)选中复选框的树节点 */
|
/** (受控)选中复选框的树节点 */
|
||||||
checkedKeys: {
|
checkedKeys: someType<Key[] | { checked: Key[]; halfChecked: Key[] }>([Array, Object]),
|
||||||
type: [Array, Object] as PropType<Key[] | { checked: Key[]; halfChecked: Key[] }>,
|
|
||||||
},
|
|
||||||
/** 默认选中复选框的树节点 */
|
/** 默认选中复选框的树节点 */
|
||||||
defaultCheckedKeys: { type: Array as PropType<Key[]> },
|
defaultCheckedKeys: arrayType<Key[]>(),
|
||||||
/** (受控)设置选中的树节点 */
|
/** (受控)设置选中的树节点 */
|
||||||
selectedKeys: { type: Array as PropType<Key[]> },
|
selectedKeys: arrayType<Key[]>(),
|
||||||
/** 默认选中的树节点 */
|
/** 默认选中的树节点 */
|
||||||
defaultSelectedKeys: { type: Array as PropType<Key[]> },
|
defaultSelectedKeys: arrayType<Key[]>(),
|
||||||
selectable: { type: Boolean, default: undefined },
|
selectable: booleanType(),
|
||||||
|
|
||||||
loadedKeys: { type: Array as PropType<Key[]> },
|
loadedKeys: arrayType<Key[]>(),
|
||||||
draggable: { type: Boolean, default: undefined },
|
draggable: booleanType(),
|
||||||
showIcon: { type: Boolean, default: undefined },
|
showIcon: booleanType(),
|
||||||
icon: { type: Function as PropType<(nodeProps: AntdTreeNodeAttribute) => any> },
|
icon: functionType<(nodeProps: AntdTreeNodeAttribute) => any>(),
|
||||||
switcherIcon: PropTypes.any,
|
switcherIcon: PropTypes.any,
|
||||||
prefixCls: String,
|
prefixCls: String,
|
||||||
/**
|
/**
|
||||||
|
@ -129,13 +128,13 @@ export const treeProps = () => {
|
||||||
* deprecated, please use `fieldNames` instead
|
* deprecated, please use `fieldNames` instead
|
||||||
* 替换treeNode中 title,key,children字段为treeData中对应的字段
|
* 替换treeNode中 title,key,children字段为treeData中对应的字段
|
||||||
*/
|
*/
|
||||||
replaceFields: { type: Object as PropType<FieldNames> },
|
replaceFields: objectType<FieldNames>(),
|
||||||
blockNode: { type: Boolean, default: undefined },
|
blockNode: booleanType(),
|
||||||
openAnimation: PropTypes.any,
|
openAnimation: PropTypes.any,
|
||||||
onDoubleclick: baseTreeProps.onDblclick,
|
onDoubleclick: baseTreeProps.onDblclick,
|
||||||
'onUpdate:selectedKeys': Function as PropType<(keys: Key[]) => void>,
|
'onUpdate:selectedKeys': functionType<(keys: Key[]) => void>(),
|
||||||
'onUpdate:checkedKeys': Function as PropType<(keys: Key[]) => void>,
|
'onUpdate:checkedKeys': functionType<(keys: Key[]) => void>(),
|
||||||
'onUpdate:expandedKeys': Function as PropType<(keys: Key[]) => void>,
|
'onUpdate:expandedKeys': functionType<(keys: Key[]) => void>(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -168,6 +167,10 @@ export default defineComponent({
|
||||||
'`children` of Tree is deprecated. Please use `treeData` instead.',
|
'`children` of Tree is deprecated. Please use `treeData` instead.',
|
||||||
);
|
);
|
||||||
const { prefixCls, direction, virtual } = useConfigInject('tree', props);
|
const { prefixCls, direction, virtual } = useConfigInject('tree', props);
|
||||||
|
|
||||||
|
// style
|
||||||
|
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||||
|
|
||||||
const treeRef = ref();
|
const treeRef = ref();
|
||||||
const scrollTo: ScrollTo = scroll => {
|
const scrollTo: ScrollTo = scroll => {
|
||||||
treeRef.value?.scrollTo(scroll);
|
treeRef.value?.scrollTo(scroll);
|
||||||
|
@ -236,7 +239,7 @@ export default defineComponent({
|
||||||
itemHeight,
|
itemHeight,
|
||||||
};
|
};
|
||||||
const children = slots.default ? filterEmpty(slots.default()) : undefined;
|
const children = slots.default ? filterEmpty(slots.default()) : undefined;
|
||||||
return (
|
return wrapSSR(
|
||||||
<VcTree
|
<VcTree
|
||||||
{...newProps}
|
{...newProps}
|
||||||
virtual={virtual.value}
|
virtual={virtual.value}
|
||||||
|
@ -251,6 +254,7 @@ export default defineComponent({
|
||||||
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
||||||
},
|
},
|
||||||
attrs.class,
|
attrs.class,
|
||||||
|
hashId.value,
|
||||||
)}
|
)}
|
||||||
direction={direction.value}
|
direction={direction.value}
|
||||||
checkable={checkable}
|
checkable={checkable}
|
||||||
|
@ -267,7 +271,7 @@ export default defineComponent({
|
||||||
checkable: () => <span class={`${prefixCls.value}-checkbox-inner`} />,
|
checkable: () => <span class={`${prefixCls.value}-checkbox-inner`} />,
|
||||||
}}
|
}}
|
||||||
children={children}
|
children={children}
|
||||||
></VcTree>
|
></VcTree>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
category: Components
|
category: Components
|
||||||
type: Data Display
|
type: Data Display
|
||||||
title: Tree
|
title: Tree
|
||||||
cover: https://gw.alipayobjects.com/zos/alicdn/Xh-oWqg9k/Tree.svg
|
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*Ag9_Q6ArswEAAAAAAAAAAAAADrJ8AQ/original
|
||||||
---
|
---
|
||||||
|
|
||||||
A hierarchical list structure component.
|
A hierarchical list structure component.
|
||||||
|
@ -17,6 +17,7 @@ Almost anything can be represented in a tree structure. Examples include directo
|
||||||
|
|
||||||
| Property | Description | Type | Default | Version |
|
| Property | Description | Type | Default | Version |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
|
| allowDrop | Whether to allow dropping on the node | ({ dropNode, dropPosition }) => boolean | - | |
|
||||||
| autoExpandParent | Whether to automatically expand a parent treeNode | boolean | false | |
|
| autoExpandParent | Whether to automatically expand a parent treeNode | boolean | false | |
|
||||||
| blockNode | Whether treeNode fill remaining horizontal space | boolean | false | |
|
| blockNode | Whether treeNode fill remaining horizontal space | boolean | false | |
|
||||||
| checkable | Adds a `Checkbox` before the treeNodes | boolean | false | |
|
| checkable | Adds a `Checkbox` before the treeNodes | boolean | false | |
|
||||||
|
@ -28,6 +29,7 @@ Almost anything can be represented in a tree structure. Examples include directo
|
||||||
| expandedKeys(v-model) | (Controlled) Specifies the keys of the expanded treeNodes | string\[] \| number\[] | \[] | |
|
| expandedKeys(v-model) | (Controlled) Specifies the keys of the expanded treeNodes | string\[] \| number\[] | \[] | |
|
||||||
| fieldNames | Replace the title,key and children fields in treeNode with the corresponding fields in treeData | object | { children:'children', title:'title', key:'key' } | 3.0.0 |
|
| fieldNames | Replace the title,key and children fields in treeNode with the corresponding fields in treeData | object | { children:'children', title:'title', key:'key' } | 3.0.0 |
|
||||||
| filterTreeNode | Defines a function to filter (highlight) treeNodes. When the function returns `true`, the corresponding treeNode will be highlighted | function(node) | - | |
|
| filterTreeNode | Defines a function to filter (highlight) treeNodes. When the function returns `true`, the corresponding treeNode will be highlighted | function(node) | - | |
|
||||||
|
| height | Config virtual scroll height. Will not support horizontal scroll when enable this | number | - | |
|
||||||
| loadData | Load data asynchronously | function(node) | - | |
|
| loadData | Load data asynchronously | function(node) | - | |
|
||||||
| loadedKeys | (Controlled) Set loaded tree nodes. Need work with `loadData` | string\[] \| number\[] | \[] | |
|
| loadedKeys | (Controlled) Set loaded tree nodes. Need work with `loadData` | string\[] \| number\[] | \[] | |
|
||||||
| multiple | Allows selecting multiple treeNodes | boolean | false | |
|
| multiple | Allows selecting multiple treeNodes | boolean | false | |
|
||||||
|
|
|
@ -3,7 +3,7 @@ category: Components
|
||||||
type: 数据展示
|
type: 数据展示
|
||||||
title: Tree
|
title: Tree
|
||||||
subtitle: 树形控件
|
subtitle: 树形控件
|
||||||
cover: https://gw.alipayobjects.com/zos/alicdn/Xh-oWqg9k/Tree.svg
|
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*Ag9_Q6ArswEAAAAAAAAAAAAADrJ8AQ/original
|
||||||
---
|
---
|
||||||
|
|
||||||
多层次的结构列表。
|
多层次的结构列表。
|
||||||
|
@ -18,6 +18,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/Xh-oWqg9k/Tree.svg
|
||||||
|
|
||||||
| 参数 | 说明 | 类型 | 默认值 | 版本 | |
|
| 参数 | 说明 | 类型 | 默认值 | 版本 | |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| allowDrop | 是否允许拖拽时放置在该节点 | ({ dropNode, dropPosition }) => boolean | - | |
|
||||||
| autoExpandParent | 是否自动展开父节点 | boolean | false | | |
|
| autoExpandParent | 是否自动展开父节点 | boolean | false | | |
|
||||||
| blockNode | 是否节点占据一行 | boolean | false | | |
|
| blockNode | 是否节点占据一行 | boolean | false | | |
|
||||||
| checkable | 节点前添加 Checkbox 复选框 | boolean | false | | |
|
| checkable | 节点前添加 Checkbox 复选框 | boolean | false | | |
|
||||||
|
@ -29,6 +30,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/Xh-oWqg9k/Tree.svg
|
||||||
| expandedKeys(v-model) | (受控)展开指定的树节点 | string\[] \| number\[] | \[] | | |
|
| expandedKeys(v-model) | (受控)展开指定的树节点 | string\[] \| number\[] | \[] | | |
|
||||||
| fieldNames | 替换 treeNode 中 title,key,children 字段为 treeData 中对应的字段 | object | {children:'children', title:'title', key:'key' } | 3.0.0 | |
|
| fieldNames | 替换 treeNode 中 title,key,children 字段为 treeData 中对应的字段 | object | {children:'children', title:'title', key:'key' } | 3.0.0 | |
|
||||||
| filterTreeNode | 按需筛选树节点(高亮),返回 true | function(node) | - | | |
|
| filterTreeNode | 按需筛选树节点(高亮),返回 true | function(node) | - | | |
|
||||||
|
| height | 设置虚拟滚动容器高度,设置后内部节点不再支持横向滚动 | number | - | |
|
||||||
| loadData | 异步加载数据 | function(node) | - | | |
|
| loadData | 异步加载数据 | function(node) | - | | |
|
||||||
| loadedKeys | (受控)已经加载的节点,需要配合 `loadData` 使用 | string\[] \| number\[] | \[] | | |
|
| loadedKeys | (受控)已经加载的节点,需要配合 `loadData` 使用 | string\[] \| number\[] | \[] | | |
|
||||||
| multiple | 支持点选多个节点(节点本身) | boolean | false | | |
|
| multiple | 支持点选多个节点(节点本身) | boolean | false | | |
|
||||||
|
|
|
@ -1,2 +1,482 @@
|
||||||
import '../../style/index.less';
|
import type { CSSInterpolation, CSSObject } from '../../_util/cssinjs';
|
||||||
import './index.less';
|
import { Keyframes } from '../../_util/cssinjs';
|
||||||
|
import { genCollapseMotion } from '../../_style/motion';
|
||||||
|
import { getStyle as getCheckboxStyle } from '../../checkbox/style';
|
||||||
|
import type { DerivativeToken } from '../../theme/internal';
|
||||||
|
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||||
|
import { genFocusOutline, resetComponent } from '../../_style';
|
||||||
|
|
||||||
|
// ============================ Keyframes =============================
|
||||||
|
const treeNodeFX = new Keyframes('ant-tree-node-fx-do-not-use', {
|
||||||
|
'0%': {
|
||||||
|
opacity: 0,
|
||||||
|
},
|
||||||
|
'100%': {
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// ============================== Switch ==============================
|
||||||
|
const getSwitchStyle = (prefixCls: string, token: DerivativeToken): CSSObject => ({
|
||||||
|
[`.${prefixCls}-switcher-icon`]: {
|
||||||
|
display: 'inline-block',
|
||||||
|
fontSize: 10,
|
||||||
|
verticalAlign: 'baseline',
|
||||||
|
|
||||||
|
svg: {
|
||||||
|
transition: `transform ${token.motionDurationSlow}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// =============================== Drop ===============================
|
||||||
|
const getDropIndicatorStyle = (prefixCls: string, token: DerivativeToken) => ({
|
||||||
|
[`.${prefixCls}-drop-indicator`]: {
|
||||||
|
position: 'absolute',
|
||||||
|
// it should displayed over the following node
|
||||||
|
zIndex: 1,
|
||||||
|
height: 2,
|
||||||
|
backgroundColor: token.colorPrimary,
|
||||||
|
borderRadius: 1,
|
||||||
|
pointerEvents: 'none',
|
||||||
|
|
||||||
|
'&:after': {
|
||||||
|
position: 'absolute',
|
||||||
|
top: -3,
|
||||||
|
insetInlineStart: -6,
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
border: `${token.lineWidthBold}px solid ${token.colorPrimary}`,
|
||||||
|
borderRadius: '50%',
|
||||||
|
content: '""',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// =============================== Base ===============================
|
||||||
|
type TreeToken = DerivativeToken & {
|
||||||
|
treeCls: string;
|
||||||
|
treeNodeCls: string;
|
||||||
|
treeNodePadding: number;
|
||||||
|
treeTitleHeight: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const genBaseStyle = (prefixCls: string, token: TreeToken): CSSObject => {
|
||||||
|
const { treeCls, treeNodeCls, treeNodePadding, treeTitleHeight } = token;
|
||||||
|
|
||||||
|
const treeCheckBoxMarginVertical = (treeTitleHeight - token.fontSizeLG) / 2;
|
||||||
|
const treeCheckBoxMarginHorizontal = token.paddingXS;
|
||||||
|
|
||||||
|
return {
|
||||||
|
[treeCls]: {
|
||||||
|
...resetComponent(token),
|
||||||
|
background: token.colorBgContainer,
|
||||||
|
borderRadius: token.borderRadius,
|
||||||
|
transition: `background-color ${token.motionDurationSlow}`,
|
||||||
|
|
||||||
|
[`&${treeCls}-rtl`]: {
|
||||||
|
// >>> Switcher
|
||||||
|
[`${treeCls}-switcher`]: {
|
||||||
|
'&_close': {
|
||||||
|
[`${treeCls}-switcher-icon`]: {
|
||||||
|
svg: {
|
||||||
|
transform: 'rotate(90deg)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&-focused:not(:hover):not(${treeCls}-active-focused)`]: {
|
||||||
|
...genFocusOutline(token),
|
||||||
|
},
|
||||||
|
|
||||||
|
// =================== Virtual List ===================
|
||||||
|
[`${treeCls}-list-holder-inner`]: {
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&${treeCls}-block-node`]: {
|
||||||
|
[`${treeCls}-list-holder-inner`]: {
|
||||||
|
alignItems: 'stretch',
|
||||||
|
|
||||||
|
// >>> Title
|
||||||
|
[`${treeCls}-node-content-wrapper`]: {
|
||||||
|
flex: 'auto',
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Drag
|
||||||
|
[`${treeNodeCls}.dragging`]: {
|
||||||
|
position: 'relative',
|
||||||
|
|
||||||
|
'&:after': {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
insetInlineEnd: 0,
|
||||||
|
bottom: treeNodePadding,
|
||||||
|
insetInlineStart: 0,
|
||||||
|
border: `1px solid ${token.colorPrimary}`,
|
||||||
|
opacity: 0,
|
||||||
|
animationName: treeNodeFX,
|
||||||
|
animationDuration: token.motionDurationSlow,
|
||||||
|
animationPlayState: 'running',
|
||||||
|
animationFillMode: 'forwards',
|
||||||
|
content: '""',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// ===================== TreeNode =====================
|
||||||
|
[`${treeNodeCls}`]: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
padding: `0 0 ${treeNodePadding}px 0`,
|
||||||
|
outline: 'none',
|
||||||
|
|
||||||
|
'&-rtl': {
|
||||||
|
direction: 'rtl',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Disabled
|
||||||
|
'&-disabled': {
|
||||||
|
// >>> Title
|
||||||
|
[`${treeCls}-node-content-wrapper`]: {
|
||||||
|
color: token.colorTextDisabled,
|
||||||
|
cursor: 'not-allowed',
|
||||||
|
'&:hover': {
|
||||||
|
background: 'transparent',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&-active ${treeCls}-node-content-wrapper`]: {
|
||||||
|
...genFocusOutline(token),
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&:not(${treeNodeCls}-disabled).filter-node ${treeCls}-title`]: {
|
||||||
|
color: 'inherit',
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-draggable': {
|
||||||
|
[`${treeCls}-draggable-icon`]: {
|
||||||
|
width: treeTitleHeight,
|
||||||
|
lineHeight: `${treeTitleHeight}px`,
|
||||||
|
textAlign: 'center',
|
||||||
|
visibility: 'visible',
|
||||||
|
opacity: 0.2,
|
||||||
|
transition: `opacity ${token.motionDurationSlow}`,
|
||||||
|
|
||||||
|
[`${treeNodeCls}:hover &`]: {
|
||||||
|
opacity: 0.45,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&${treeNodeCls}-disabled`]: {
|
||||||
|
[`${treeCls}-draggable-icon`]: {
|
||||||
|
visibility: 'hidden',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Indent
|
||||||
|
[`${treeCls}-indent`]: {
|
||||||
|
alignSelf: 'stretch',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
userSelect: 'none',
|
||||||
|
'&-unit': {
|
||||||
|
display: 'inline-block',
|
||||||
|
width: treeTitleHeight,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Drag Handler
|
||||||
|
[`${treeCls}-draggable-icon`]: {
|
||||||
|
visibility: 'hidden',
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Switcher
|
||||||
|
[`${treeCls}-switcher`]: {
|
||||||
|
...getSwitchStyle(prefixCls, token),
|
||||||
|
position: 'relative',
|
||||||
|
flex: 'none',
|
||||||
|
alignSelf: 'stretch',
|
||||||
|
width: treeTitleHeight,
|
||||||
|
margin: 0,
|
||||||
|
lineHeight: `${treeTitleHeight}px`,
|
||||||
|
textAlign: 'center',
|
||||||
|
cursor: 'pointer',
|
||||||
|
userSelect: 'none',
|
||||||
|
|
||||||
|
'&-noop': {
|
||||||
|
cursor: 'default',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&_close': {
|
||||||
|
[`${treeCls}-switcher-icon`]: {
|
||||||
|
svg: {
|
||||||
|
transform: 'rotate(-90deg)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-loading-icon': {
|
||||||
|
color: token.colorPrimary,
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-leaf-line': {
|
||||||
|
position: 'relative',
|
||||||
|
zIndex: 1,
|
||||||
|
display: 'inline-block',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
|
||||||
|
// https://github.com/ant-design/ant-design/issues/31884
|
||||||
|
'&:before': {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
insetInlineEnd: treeTitleHeight / 2,
|
||||||
|
bottom: -treeNodePadding,
|
||||||
|
marginInlineStart: -1,
|
||||||
|
borderInlineEnd: `1px solid ${token.colorBorder}`,
|
||||||
|
content: '""',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:after': {
|
||||||
|
position: 'absolute',
|
||||||
|
width: (treeTitleHeight / 2) * 0.8,
|
||||||
|
height: treeTitleHeight / 2,
|
||||||
|
borderBottom: `1px solid ${token.colorBorder}`,
|
||||||
|
content: '""',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Checkbox
|
||||||
|
[`${treeCls}-checkbox`]: {
|
||||||
|
top: 'initial',
|
||||||
|
marginInlineEnd: treeCheckBoxMarginHorizontal,
|
||||||
|
marginBlockStart: treeCheckBoxMarginVertical,
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Title
|
||||||
|
// add `${treeCls}-checkbox + span` to cover checkbox `${checkboxCls} + span`
|
||||||
|
[`${treeCls}-node-content-wrapper, ${treeCls}-checkbox + span`]: {
|
||||||
|
position: 'relative',
|
||||||
|
zIndex: 'auto',
|
||||||
|
minHeight: treeTitleHeight,
|
||||||
|
margin: 0,
|
||||||
|
padding: `0 ${token.paddingXS / 2}px`,
|
||||||
|
color: 'inherit',
|
||||||
|
lineHeight: `${treeTitleHeight}px`,
|
||||||
|
background: 'transparent',
|
||||||
|
borderRadius: token.borderRadius,
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: `all ${token.motionDurationMid}, border 0s, line-height 0s, box-shadow 0s`,
|
||||||
|
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: token.controlItemBgHover,
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&${treeCls}-node-selected`]: {
|
||||||
|
backgroundColor: token.controlItemBgActive,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Icon
|
||||||
|
[`${treeCls}-iconEle`]: {
|
||||||
|
display: 'inline-block',
|
||||||
|
width: treeTitleHeight,
|
||||||
|
height: treeTitleHeight,
|
||||||
|
lineHeight: `${treeTitleHeight}px`,
|
||||||
|
textAlign: 'center',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
|
||||||
|
'&:empty': {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// https://github.com/ant-design/ant-design/issues/28217
|
||||||
|
[`${treeCls}-unselectable ${treeCls}-node-content-wrapper:hover`]: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== Draggable =====================
|
||||||
|
[`${treeCls}-node-content-wrapper`]: {
|
||||||
|
lineHeight: `${treeTitleHeight}px`,
|
||||||
|
userSelect: 'none',
|
||||||
|
|
||||||
|
...getDropIndicatorStyle(prefixCls, token),
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${treeNodeCls}.drop-container`]: {
|
||||||
|
'> [draggable]': {
|
||||||
|
boxShadow: `0 0 0 2px ${token.colorPrimary}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== Show Line =====================
|
||||||
|
'&-show-line': {
|
||||||
|
// ================ Indent lines ================
|
||||||
|
[`${treeCls}-indent`]: {
|
||||||
|
'&-unit': {
|
||||||
|
position: 'relative',
|
||||||
|
height: '100%',
|
||||||
|
|
||||||
|
'&:before': {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
insetInlineEnd: treeTitleHeight / 2,
|
||||||
|
bottom: -treeNodePadding,
|
||||||
|
borderInlineEnd: `1px solid ${token.colorBorder}`,
|
||||||
|
content: '""',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-end': {
|
||||||
|
'&:before': {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============== Cover Background ==============
|
||||||
|
[`${treeCls}-switcher`]: {
|
||||||
|
background: 'transparent',
|
||||||
|
|
||||||
|
'&-line-icon': {
|
||||||
|
// https://github.com/ant-design/ant-design/issues/32813
|
||||||
|
verticalAlign: '-0.15em',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${treeNodeCls}-leaf-last`]: {
|
||||||
|
[`${treeCls}-switcher`]: {
|
||||||
|
'&-leaf-line': {
|
||||||
|
'&:before': {
|
||||||
|
top: 'auto !important',
|
||||||
|
bottom: 'auto !important',
|
||||||
|
height: `${treeTitleHeight / 2}px !important`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================ Directory =============================
|
||||||
|
export const genDirectoryStyle = (token: TreeToken): CSSObject => {
|
||||||
|
const { treeCls, treeNodeCls, treeNodePadding } = token;
|
||||||
|
|
||||||
|
return {
|
||||||
|
[`${treeCls}${treeCls}-directory`]: {
|
||||||
|
// ================== TreeNode ==================
|
||||||
|
[treeNodeCls]: {
|
||||||
|
position: 'relative',
|
||||||
|
|
||||||
|
// Hover color
|
||||||
|
'&:before': {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
insetInlineEnd: 0,
|
||||||
|
bottom: treeNodePadding,
|
||||||
|
insetInlineStart: 0,
|
||||||
|
transition: `background-color ${token.motionDurationMid}`,
|
||||||
|
content: '""',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:hover': {
|
||||||
|
'&:before': {
|
||||||
|
background: token.controlItemBgHover,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Elements
|
||||||
|
'> *': {
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Switcher
|
||||||
|
[`${treeCls}-switcher`]: {
|
||||||
|
transition: `color ${token.motionDurationMid}`,
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Title
|
||||||
|
[`${treeCls}-node-content-wrapper`]: {
|
||||||
|
borderRadius: 0,
|
||||||
|
userSelect: 'none',
|
||||||
|
|
||||||
|
'&:hover': {
|
||||||
|
background: 'transparent',
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&${treeCls}-node-selected`]: {
|
||||||
|
color: token.colorTextLightSolid,
|
||||||
|
background: 'transparent',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// ============= Selected =============
|
||||||
|
'&-selected': {
|
||||||
|
[`
|
||||||
|
&:hover::before,
|
||||||
|
&::before
|
||||||
|
`]: {
|
||||||
|
background: token.colorPrimary,
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Switcher
|
||||||
|
[`${treeCls}-switcher`]: {
|
||||||
|
color: token.colorTextLightSolid,
|
||||||
|
},
|
||||||
|
|
||||||
|
// >>> Title
|
||||||
|
[`${treeCls}-node-content-wrapper`]: {
|
||||||
|
color: token.colorTextLightSolid,
|
||||||
|
background: 'transparent',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================== Merged ==============================
|
||||||
|
export const genTreeStyle = (prefixCls: string, token: DerivativeToken): CSSInterpolation => {
|
||||||
|
const treeCls = `.${prefixCls}`;
|
||||||
|
const treeNodeCls = `${treeCls}-treenode`;
|
||||||
|
|
||||||
|
const treeNodePadding = token.paddingXS / 2;
|
||||||
|
const treeTitleHeight = token.controlHeightSM;
|
||||||
|
|
||||||
|
const treeToken = mergeToken<TreeToken>(token, {
|
||||||
|
treeCls,
|
||||||
|
treeNodeCls,
|
||||||
|
treeNodePadding,
|
||||||
|
treeTitleHeight,
|
||||||
|
});
|
||||||
|
|
||||||
|
return [
|
||||||
|
// Basic
|
||||||
|
genBaseStyle(prefixCls, treeToken),
|
||||||
|
// Directory
|
||||||
|
genDirectoryStyle(treeToken),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================== Export ==============================
|
||||||
|
export default genComponentStyleHook('Tree', (token, { prefixCls }) => [
|
||||||
|
{
|
||||||
|
[token.componentCls]: getCheckboxStyle(`${prefixCls}-checkbox`, token),
|
||||||
|
},
|
||||||
|
genTreeStyle(prefixCls, token),
|
||||||
|
genCollapseMotion(token),
|
||||||
|
]);
|
||||||
|
|
Loading…
Reference in New Issue