Browse Source

refactor: tree select (#6296)

pull/6299/head
果冻橙 2 years ago committed by GitHub
parent
commit
799eeed346
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      components/style.ts
  2. 2
      components/tree-select/index.en-US.md
  3. 145
      components/tree-select/index.tsx
  4. 2
      components/tree-select/index.zh-CN.md
  5. 57
      components/tree-select/style/index.less
  6. 79
      components/tree-select/style/index.tsx

2
components/style.ts

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

2
components/tree-select/index.en-US.md

@ -2,7 +2,7 @@
category: Components
type: Data Entry
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.

145
components/tree-select/index.tsx

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

2
components/tree-select/index.zh-CN.md

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

57
components/tree-select/style/index.less

@ -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);
}
}
}
}

79
components/tree-select/style/index.tsx

@ -1,7 +1,74 @@
import '../../style/index.less';
import './index.less';
import type { Ref } from 'vue';
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
// deps-lint-skip: tree, form
import '../../select/style';
import '../../empty/style';
interface TreeSelectToken extends FullToken<'TreeSelect'> {
treePrefixCls: string;
}
// =============================== 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