refactor: tree select (#6296)

pull/6299/head
果冻橙 2 years ago committed by GitHub
parent 124aae72a4
commit 799eeed346
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -47,7 +47,7 @@ import './cascader/style';
// import './layout/style'; // import './layout/style';
// import './anchor/style'; // import './anchor/style';
// import './list/style'; // import './list/style';
import './tree-select/style'; // import './tree-select/style';
import './drawer/style'; import './drawer/style';
// import './skeleton/style'; // import './skeleton/style';
// import './comment/style'; // import './comment/style';

@ -2,7 +2,7 @@
category: Components category: Components
type: Data Entry type: Data Entry
title: TreeSelect title: TreeSelect
cover: https://gw.alipayobjects.com/zos/alicdn/Ax4DA0njr/TreeSelect.svg cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*DfTMRYSDngEAAAAAAAAAAAAADrJ8AQ/original
--- ---
Tree selection control. Tree selection control.

@ -1,4 +1,4 @@
import type { App, ExtractPropTypes, PropType } from 'vue'; import type { App, ExtractPropTypes } from 'vue';
import { computed, ref, watchEffect, defineComponent } from 'vue'; import { computed, ref, watchEffect, defineComponent } from 'vue';
import VcTreeSelect, { import VcTreeSelect, {
TreeNode, TreeNode,
@ -28,6 +28,11 @@ import type { SelectCommonPlacement } from '../_util/transition';
import { getTransitionDirection } from '../_util/transition'; import { getTransitionDirection } from '../_util/transition';
import type { InputStatus } from '../_util/statusUtils'; import type { InputStatus } from '../_util/statusUtils';
import { getStatusClassNames, getMergedStatus } from '../_util/statusUtils'; import { getStatusClassNames, getMergedStatus } from '../_util/statusUtils';
import { booleanType, stringType, objectType, someType, functionType } from '../_util/type';
// CSSINJS
import useSelectStyle from '../select/style';
import useStyle from './style';
const getTransitionName = (rootPrefixCls: string, motion: string, transitionName?: string) => { const getTransitionName = (rootPrefixCls: string, motion: string, transitionName?: string) => {
if (transitionName !== undefined) { if (transitionName !== undefined) {
@ -62,15 +67,15 @@ export function treeSelectProps<
'customSlots', 'customSlots',
]), ]),
suffixIcon: PropTypes.any, suffixIcon: PropTypes.any,
size: { type: String as PropType<SizeType> }, size: stringType<SizeType>(),
bordered: { type: Boolean, default: undefined }, bordered: booleanType(),
treeLine: { type: [Boolean, Object] as PropType<TreeProps['showLine']>, default: undefined }, treeLine: someType<TreeProps['showLine']>([Boolean, Object]),
replaceFields: { type: Object as PropType<FieldNames> }, replaceFields: objectType<FieldNames>(),
placement: String as PropType<SelectCommonPlacement>, placement: stringType<SelectCommonPlacement>(),
status: String as PropType<InputStatus>, status: stringType<InputStatus>(),
'onUpdate:value': { type: Function as PropType<(value: any) => void> }, 'onUpdate:value': functionType<(value: any) => void>(),
'onUpdate:treeExpandedKeys': { type: Function as PropType<(keys: Key[]) => void> }, 'onUpdate:treeExpandedKeys': functionType<(keys: Key[]) => void>(),
'onUpdate:searchValue': { type: Function as PropType<(value: string) => void> }, 'onUpdate:searchValue': functionType<(value: string) => void>(),
}; };
} }
export type TreeSelectProps = Partial<ExtractPropTypes<ReturnType<typeof treeSelectProps>>>; export type TreeSelectProps = Partial<ExtractPropTypes<ReturnType<typeof treeSelectProps>>>;
@ -149,10 +154,19 @@ const TreeSelect = defineComponent({
const treePrefixCls = computed(() => getPrefixCls('select-tree', props.prefixCls)); const treePrefixCls = computed(() => getPrefixCls('select-tree', props.prefixCls));
const treeSelectPrefixCls = computed(() => getPrefixCls('tree-select', props.prefixCls)); const treeSelectPrefixCls = computed(() => getPrefixCls('tree-select', props.prefixCls));
// style
const [wrapSelectSSR, hashId] = useSelectStyle(prefixCls);
const [wrapTreeSelectSSR] = useStyle(treeSelectPrefixCls, treePrefixCls);
const mergedDropdownClassName = computed(() => const mergedDropdownClassName = computed(() =>
classNames(props.dropdownClassName, `${treeSelectPrefixCls.value}-dropdown`, { classNames(
[`${treeSelectPrefixCls.value}-dropdown-rtl`]: direction.value === 'rtl', props.dropdownClassName,
}), `${treeSelectPrefixCls.value}-dropdown`,
{
[`${treeSelectPrefixCls.value}-dropdown-rtl`]: direction.value === 'rtl',
},
hashId.value,
),
); );
const isMultiple = computed(() => !!(props.treeCheckable || props.multiple)); const isMultiple = computed(() => !!(props.treeCheckable || props.multiple));
@ -249,62 +263,65 @@ const TreeSelect = defineComponent({
}, },
getStatusClassNames(prefixCls.value, mergedStatus.value, hasFeedback), getStatusClassNames(prefixCls.value, mergedStatus.value, hasFeedback),
attrs.class, attrs.class,
hashId.value,
); );
const otherProps: any = {}; const otherProps: any = {};
if (props.treeData === undefined && slots.default) { if (props.treeData === undefined && slots.default) {
otherProps.children = flattenChildren(slots.default()); otherProps.children = flattenChildren(slots.default());
} }
return ( return wrapSelectSSR(
<VcTreeSelect wrapTreeSelectSSR(
{...attrs} <VcTreeSelect
{...selectProps} {...attrs}
virtual={virtual.value} {...selectProps}
dropdownMatchSelectWidth={dropdownMatchSelectWidth.value} virtual={virtual.value}
id={id} dropdownMatchSelectWidth={dropdownMatchSelectWidth.value}
fieldNames={fieldNames} id={id}
ref={treeSelectRef} fieldNames={fieldNames}
prefixCls={prefixCls.value} ref={treeSelectRef}
class={mergedClassName} prefixCls={prefixCls.value}
listHeight={listHeight} class={mergedClassName}
listItemHeight={listItemHeight} listHeight={listHeight}
treeLine={!!treeLine} listItemHeight={listItemHeight}
inputIcon={suffixIcon} treeLine={!!treeLine}
multiple={multiple} inputIcon={suffixIcon}
removeIcon={removeIcon} multiple={multiple}
clearIcon={clearIcon} removeIcon={removeIcon}
switcherIcon={(nodeProps: SwitcherIconProps) => clearIcon={clearIcon}
renderSwitcherIcon( switcherIcon={(nodeProps: SwitcherIconProps) =>
treePrefixCls.value, renderSwitcherIcon(
switcherIcon, treePrefixCls.value,
nodeProps, switcherIcon,
slots.leafIcon, nodeProps,
treeLine, slots.leafIcon,
) treeLine,
} )
showTreeIcon={treeIcon as any} }
notFoundContent={mergedNotFound} showTreeIcon={treeIcon as any}
getPopupContainer={getPopupContainer.value} notFoundContent={mergedNotFound}
treeMotion={null} getPopupContainer={getPopupContainer.value}
dropdownClassName={mergedDropdownClassName.value} treeMotion={null}
choiceTransitionName={choiceTransitionName.value} dropdownClassName={mergedDropdownClassName.value}
onChange={handleChange} choiceTransitionName={choiceTransitionName.value}
onBlur={handleBlur} onChange={handleChange}
onSearch={handleSearch} onBlur={handleBlur}
onTreeExpand={handleTreeExpand} onSearch={handleSearch}
v-slots={{ onTreeExpand={handleTreeExpand}
...slots, v-slots={{
treeCheckable: () => <span class={`${prefixCls.value}-tree-checkbox-inner`} />, ...slots,
}} treeCheckable: () => <span class={`${prefixCls.value}-tree-checkbox-inner`} />,
{...otherProps} }}
transitionName={transitionName.value} {...otherProps}
customSlots={{ transitionName={transitionName.value}
...slots, customSlots={{
treeCheckable: () => <span class={`${prefixCls.value}-tree-checkbox-inner`} />, ...slots,
}} treeCheckable: () => <span class={`${prefixCls.value}-tree-checkbox-inner`} />,
maxTagPlaceholder={props.maxTagPlaceholder || slots.maxTagPlaceholder} }}
placement={placement.value} maxTagPlaceholder={props.maxTagPlaceholder || slots.maxTagPlaceholder}
showArrow={hasFeedback || showArrow} placement={placement.value}
/> showArrow={hasFeedback || showArrow}
/>,
),
); );
}; };
}, },

@ -3,7 +3,7 @@ category: Components
type: 数据录入 type: 数据录入
title: TreeSelect title: TreeSelect
subtitle: 树选择 subtitle: 树选择
cover: https://gw.alipayobjects.com/zos/alicdn/Ax4DA0njr/TreeSelect.svg cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*DfTMRYSDngEAAAAAAAAAAAAADrJ8AQ/original
--- ---
树型选择控件。 树型选择控件。

@ -1,57 +0,0 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@import '../../tree/style/mixin';
@import '../../checkbox/style/mixin';
@tree-select-prefix-cls: ~'@{ant-prefix}-tree-select';
@select-tree-prefix-cls: ~'@{ant-prefix}-select-tree';
.antCheckboxFn(@checkbox-prefix-cls: ~'@{select-tree-prefix-cls}-checkbox');
.@{tree-select-prefix-cls} {
// ======================= Dropdown =======================
&-dropdown {
padding: @padding-xs (@padding-xs / 2);
&-rtl {
direction: rtl;
}
// ======================== Tree ========================
.@{select-tree-prefix-cls} {
border-radius: 0;
&-list-holder-inner {
align-items: stretch;
.@{select-tree-prefix-cls}-treenode {
.@{select-tree-prefix-cls}-node-content-wrapper {
flex: auto;
}
}
}
}
}
}
.@{select-tree-prefix-cls} {
.antTreeFn(@select-tree-prefix-cls);
// change switcher icon rotation in rtl direction
& &-switcher {
&_close {
.@{select-tree-prefix-cls}-switcher-icon {
svg {
.@{tree-select-prefix-cls}-dropdown-rtl & {
transform: rotate(90deg);
}
}
}
}
&-loading-icon {
.@{tree-select-prefix-cls}-dropdown-rtl & {
transform: scaleY(-1);
}
}
}
}

@ -1,7 +1,74 @@
import '../../style/index.less'; import type { Ref } from 'vue';
import './index.less'; import { getStyle as getCheckboxStyle } from '../../checkbox/style';
import type { AliasToken, FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { genTreeStyle } from '../../tree/style';
// style dependencies interface TreeSelectToken extends FullToken<'TreeSelect'> {
// deps-lint-skip: tree, form treePrefixCls: string;
import '../../select/style'; }
import '../../empty/style';
// =============================== Base ===============================
const genBaseStyle: GenerateStyle<TreeSelectToken> = token => {
const { componentCls, treePrefixCls, colorBgElevated } = token;
const treeCls = `.${treePrefixCls}`;
return [
// ======================================================
// == Dropdown ==
// ======================================================
{
[`${componentCls}-dropdown`]: [
{
padding: `${token.paddingXS}px ${token.paddingXS / 2}px`,
},
// ====================== Tree ======================
genTreeStyle(
treePrefixCls,
mergeToken<AliasToken>(token, { colorBgContainer: colorBgElevated }),
),
{
[treeCls]: {
borderRadius: 0,
'&-list-holder-inner': {
alignItems: 'stretch',
[`${treeCls}-treenode`]: {
[`${treeCls}-node-content-wrapper`]: {
flex: 'auto',
},
},
},
},
},
// ==================== Checkbox ====================
getCheckboxStyle(`${treePrefixCls}-checkbox`, token),
// ====================== RTL =======================
{
'&-rtl': {
direction: 'rtl',
[`${treeCls}-switcher${treeCls}-switcher_close`]: {
[`${treeCls}-switcher-icon svg`]: {
transform: 'rotate(90deg)',
},
},
},
},
],
},
];
};
// ============================== Export ==============================
export default function useTreeSelectStyle(prefixCls: Ref<string>, treePrefixCls: Ref<string>) {
return genComponentStyleHook('TreeSelect', token => {
const treeSelectToken = mergeToken<TreeSelectToken>(token, {
treePrefixCls: treePrefixCls.value,
});
return [genBaseStyle(treeSelectToken)];
})(prefixCls);
}

Loading…
Cancel
Save