diff --git a/components/style.ts b/components/style.ts index 7a14b582a..6639fcd9c 100644 --- a/components/style.ts +++ b/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'; diff --git a/components/tree-select/index.en-US.md b/components/tree-select/index.en-US.md index 8ed288e02..4cb1769de 100644 --- a/components/tree-select/index.en-US.md +++ b/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. diff --git a/components/tree-select/index.tsx b/components/tree-select/index.tsx index 680492f65..1aa425302 100644 --- a/components/tree-select/index.tsx +++ b/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 }, - bordered: { type: Boolean, default: undefined }, - treeLine: { type: [Boolean, Object] as PropType, default: undefined }, - replaceFields: { type: Object as PropType }, - placement: String as PropType, - status: String as PropType, - '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(), + bordered: booleanType(), + treeLine: someType([Boolean, Object]), + replaceFields: objectType(), + placement: stringType(), + status: stringType(), + 'onUpdate:value': functionType<(value: any) => void>(), + 'onUpdate:treeExpandedKeys': functionType<(keys: Key[]) => void>(), + 'onUpdate:searchValue': functionType<(value: string) => void>(), }; } export type TreeSelectProps = Partial>>; @@ -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 ( - - 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: () => , - }} - {...otherProps} - transitionName={transitionName.value} - customSlots={{ - ...slots, - treeCheckable: () => , - }} - maxTagPlaceholder={props.maxTagPlaceholder || slots.maxTagPlaceholder} - placement={placement.value} - showArrow={hasFeedback || showArrow} - /> + return wrapSelectSSR( + wrapTreeSelectSSR( + + 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: () => , + }} + {...otherProps} + transitionName={transitionName.value} + customSlots={{ + ...slots, + treeCheckable: () => , + }} + maxTagPlaceholder={props.maxTagPlaceholder || slots.maxTagPlaceholder} + placement={placement.value} + showArrow={hasFeedback || showArrow} + />, + ), ); }; }, diff --git a/components/tree-select/index.zh-CN.md b/components/tree-select/index.zh-CN.md index 6486416bc..777b49524 100644 --- a/components/tree-select/index.zh-CN.md +++ b/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 --- 树型选择控件。 diff --git a/components/tree-select/style/index.less b/components/tree-select/style/index.less deleted file mode 100644 index b2cf719f3..000000000 --- a/components/tree-select/style/index.less +++ /dev/null @@ -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); - } - } - } -} diff --git a/components/tree-select/style/index.tsx b/components/tree-select/style/index.tsx index def4cc2b8..bc8102685 100644 --- a/components/tree-select/style/index.tsx +++ b/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 = 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(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, treePrefixCls: Ref) { + return genComponentStyleHook('TreeSelect', token => { + const treeSelectToken = mergeToken(token, { + treePrefixCls: treePrefixCls.value, + }); + return [genBaseStyle(treeSelectToken)]; + })(prefixCls); +}