refactor:transfer (#6247)
* refactor:transfer * merge v4 branch & fix theme interface conflict * docs:update & refactor: transfer typepull/6263/head^2
parent
bbfb3cef7d
commit
68d295d7ef
|
@ -41,7 +41,7 @@ import './table/style';
|
||||||
// import './progress/style';
|
// import './progress/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';
|
||||||
|
|
|
@ -42,7 +42,7 @@ import type { ComponentToken as SpinComponentToken } from '../../spin/style';
|
||||||
import type { ComponentToken as TagComponentToken } from '../../tag/style';
|
import type { ComponentToken as TagComponentToken } from '../../tag/style';
|
||||||
// import type { ComponentToken as TimelineComponentToken } from '../../timeline/style';
|
// import type { ComponentToken as TimelineComponentToken } from '../../timeline/style';
|
||||||
import type { ComponentToken as TooltipComponentToken } from '../../tooltip/style';
|
import type { ComponentToken as TooltipComponentToken } from '../../tooltip/style';
|
||||||
// import type { ComponentToken as TransferComponentToken } from '../../transfer/style';
|
import type { ComponentToken as TransferComponentToken } from '../../transfer/style';
|
||||||
import type { ComponentToken as TypographyComponentToken } from '../../typography/style';
|
import type { ComponentToken as TypographyComponentToken } from '../../typography/style';
|
||||||
// import type { ComponentToken as UploadComponentToken } from '../../upload/style';
|
// import type { ComponentToken as UploadComponentToken } from '../../upload/style';
|
||||||
// import type { ComponentToken as TourComponentToken } from '../../tour/style';
|
// import type { ComponentToken as TourComponentToken } from '../../tour/style';
|
||||||
|
@ -100,7 +100,7 @@ export interface ComponentTokenMap {
|
||||||
TreeSelect?: {};
|
TreeSelect?: {};
|
||||||
Typography?: TypographyComponentToken;
|
Typography?: TypographyComponentToken;
|
||||||
// Timeline?: TimelineComponentToken;
|
// Timeline?: TimelineComponentToken;
|
||||||
// Transfer?: TransferComponentToken;
|
Transfer?: TransferComponentToken;
|
||||||
// Tabs?: TabsComponentToken;
|
// Tabs?: TabsComponentToken;
|
||||||
// Calendar?: CalendarComponentToken;
|
// Calendar?: CalendarComponentToken;
|
||||||
// Steps?: StepsComponentToken;
|
// Steps?: StepsComponentToken;
|
||||||
|
|
|
@ -5,13 +5,14 @@ import ListItem from './ListItem';
|
||||||
import Pagination from '../pagination';
|
import Pagination from '../pagination';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import type { TransferItem } from '.';
|
import type { TransferItem } from '.';
|
||||||
|
import { booleanType } from '../_util/type';
|
||||||
|
|
||||||
export const transferListBodyProps = {
|
export const transferListBodyProps = {
|
||||||
prefixCls: String,
|
prefixCls: String,
|
||||||
filteredRenderItems: PropTypes.array.def([]),
|
filteredRenderItems: PropTypes.array.def([]),
|
||||||
selectedKeys: PropTypes.array,
|
selectedKeys: PropTypes.array,
|
||||||
disabled: { type: Boolean, default: undefined },
|
disabled: booleanType(),
|
||||||
showRemove: { type: Boolean, default: undefined },
|
showRemove: booleanType(),
|
||||||
pagination: PropTypes.any,
|
pagination: PropTypes.any,
|
||||||
onItemSelect: Function,
|
onItemSelect: Function,
|
||||||
onScroll: Function,
|
onScroll: Function,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import TransButton from '../_util/transButton';
|
||||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||||
import type { ExtractPropTypes } from 'vue';
|
import type { ExtractPropTypes } from 'vue';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import { booleanType } from '../_util/type';
|
||||||
|
|
||||||
function noop() {}
|
function noop() {}
|
||||||
|
|
||||||
|
@ -15,10 +16,10 @@ export const transferListItemProps = {
|
||||||
renderedText: PropTypes.any,
|
renderedText: PropTypes.any,
|
||||||
renderedEl: PropTypes.any,
|
renderedEl: PropTypes.any,
|
||||||
item: PropTypes.any,
|
item: PropTypes.any,
|
||||||
checked: { type: Boolean, default: undefined },
|
checked: booleanType(),
|
||||||
prefixCls: String,
|
prefixCls: String,
|
||||||
disabled: { type: Boolean, default: undefined },
|
disabled: booleanType(),
|
||||||
showRemove: { type: Boolean, default: undefined },
|
showRemove: booleanType(),
|
||||||
onClick: Function,
|
onClick: Function,
|
||||||
onRemove: Function,
|
onRemove: Function,
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
<docs>
|
||||||
|
---
|
||||||
|
order: 4
|
||||||
|
title:
|
||||||
|
zh-CN: 自定义全选文字
|
||||||
|
en-US: Custom Select All Labels
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
自定义穿梭框全选按钮的文字。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
Custom the labels for select all checkboxs.
|
||||||
|
|
||||||
|
</docs>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-transfer
|
||||||
|
v-model:target-keys="targetKeys"
|
||||||
|
v-model:selected-keys="selectedKeys"
|
||||||
|
:data-source="mockData"
|
||||||
|
:titles="['Source', 'Target']"
|
||||||
|
:render="item => item.title"
|
||||||
|
:select-all-labels="selectAllLabels"
|
||||||
|
:disabled="disabled"
|
||||||
|
@change="handleChange"
|
||||||
|
@selectChange="handleSelectChange"
|
||||||
|
@scroll="handleScroll"
|
||||||
|
/>
|
||||||
|
<a-switch
|
||||||
|
v-model:checked="disabled"
|
||||||
|
un-checked-children="enabled"
|
||||||
|
checked-children="disabled"
|
||||||
|
style="margin-top: 16px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref } from 'vue';
|
||||||
|
import type { SelectAllLabel } from 'ant-design-vue/es/transfer';
|
||||||
|
|
||||||
|
interface MockData {
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
disabled: boolean;
|
||||||
|
}
|
||||||
|
const mockData: MockData[] = [];
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
mockData.push({
|
||||||
|
key: i.toString(),
|
||||||
|
title: `content${i + 1}`,
|
||||||
|
description: `description of content${i + 1}`,
|
||||||
|
disabled: i % 3 < 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const oriTargetKeys = mockData.filter(item => +item.key % 3 > 1).map(item => item.key);
|
||||||
|
export default defineComponent({
|
||||||
|
data() {
|
||||||
|
const disabled = ref<boolean>(false);
|
||||||
|
|
||||||
|
const targetKeys = ref<string[]>(oriTargetKeys);
|
||||||
|
|
||||||
|
const selectedKeys = ref<string[]>(['1', '4']);
|
||||||
|
|
||||||
|
const handleChange = (nextTargetKeys: string[], direction: string, moveKeys: string[]) => {
|
||||||
|
console.log('targetKeys: ', nextTargetKeys);
|
||||||
|
console.log('direction: ', direction);
|
||||||
|
console.log('moveKeys: ', moveKeys);
|
||||||
|
};
|
||||||
|
const handleSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
|
||||||
|
console.log('sourceSelectedKeys: ', sourceSelectedKeys);
|
||||||
|
console.log('targetSelectedKeys: ', targetSelectedKeys);
|
||||||
|
};
|
||||||
|
const handleScroll = (direction: string, e: Event) => {
|
||||||
|
console.log('direction:', direction);
|
||||||
|
console.log('target:', e.target);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectAllLabels: SelectAllLabel[] = [
|
||||||
|
'Select All',
|
||||||
|
({ selectedCount, totalCount }) => `${selectedCount}/${totalCount}`,
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
mockData,
|
||||||
|
targetKeys,
|
||||||
|
selectedKeys,
|
||||||
|
disabled,
|
||||||
|
selectAllLabels,
|
||||||
|
handleChange,
|
||||||
|
handleSelectChange,
|
||||||
|
handleScroll,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -9,6 +9,7 @@
|
||||||
<table-transfer />
|
<table-transfer />
|
||||||
<tree-transfer />
|
<tree-transfer />
|
||||||
<statusVue />
|
<statusVue />
|
||||||
|
<custom-select-all-labels></custom-select-all-labels>
|
||||||
</demo-sort>
|
</demo-sort>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
@ -17,6 +18,7 @@ import Oneway from './oneway.vue';
|
||||||
import Search from './search.vue';
|
import Search from './search.vue';
|
||||||
import Advanced from './advanced.vue';
|
import Advanced from './advanced.vue';
|
||||||
import CustomItem from './custom-item.vue';
|
import CustomItem from './custom-item.vue';
|
||||||
|
import CustomSelectAllLabels from './custom-select-all-labels.vue';
|
||||||
import TableTransfer from './table-transfer.vue';
|
import TableTransfer from './table-transfer.vue';
|
||||||
import TreeTransfer from './tree-transfer.vue';
|
import TreeTransfer from './tree-transfer.vue';
|
||||||
import Pagination from './pagination.vue';
|
import Pagination from './pagination.vue';
|
||||||
|
@ -35,6 +37,7 @@ export default defineComponent({
|
||||||
Search,
|
Search,
|
||||||
Advanced,
|
Advanced,
|
||||||
CustomItem,
|
CustomItem,
|
||||||
|
CustomSelectAllLabels,
|
||||||
Pagination,
|
Pagination,
|
||||||
TableTransfer,
|
TableTransfer,
|
||||||
TreeTransfer,
|
TreeTransfer,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
category: Components
|
category: Components
|
||||||
type: Data Entry
|
type: Data Entry
|
||||||
title: Transfer
|
title: Transfer
|
||||||
cover: https://gw.alipayobjects.com/zos/alicdn/QAXskNI4G/Transfer.svg
|
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*EAApQ5ephigAAAAAAAAAAAAADrJ8AQ/original
|
||||||
---
|
---
|
||||||
|
|
||||||
Alert component for feedback.
|
Alert component for feedback.
|
||||||
|
@ -31,6 +31,7 @@ One or more elements can be selected from either column, one click on the proper
|
||||||
| operationStyle | A custom CSS style used for rendering the operations column | CSSProperties | - | 3.0.0 |
|
| operationStyle | A custom CSS style used for rendering the operations column | CSSProperties | - | 3.0.0 |
|
||||||
| pagination | Use pagination. Not work in render props | boolean \| { pageSize: number, simple: boolean, showSizeChanger?: boolean, showLessItems?: boolean } | false | 3.0.0 |
|
| pagination | Use pagination. Not work in render props | boolean \| { pageSize: number, simple: boolean, showSizeChanger?: boolean, showLessItems?: boolean } | false | 3.0.0 |
|
||||||
| render | The function to generate the item shown on a column. Based on an record (element of the dataSource array), this function should return a element which is generated from that record. Also, it can return a plain object with `value` and `label`, `label` is a element and `value` is for title | Function(record) \| slot | | |
|
| render | The function to generate the item shown on a column. Based on an record (element of the dataSource array), this function should return a element which is generated from that record. Also, it can return a plain object with `value` and `label`, `label` is a element and `value` is for title | Function(record) \| slot | | |
|
||||||
|
| selectAllLabels | A set of customized labels for select all checkboxes on the header | VueNode \| ((info: { selectedCount: number; totalCount: number }) => VueNode); | - | 3.0.0 |
|
||||||
| selectedKeys(v-model) | A set of keys of selected items. | string\[] | \[] | |
|
| selectedKeys(v-model) | A set of keys of selected items. | string\[] | \[] | |
|
||||||
| showSearch | If included, a search box is shown on each column. | boolean | false | |
|
| showSearch | If included, a search box is shown on each column. | boolean | false | |
|
||||||
| showSelectAll | Show select all checkbox on the header | boolean | true | |
|
| showSelectAll | Show select all checkbox on the header | boolean | true | |
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { CSSProperties, ExtractPropTypes, PropType } from 'vue';
|
import type { CSSProperties, ExtractPropTypes } from 'vue';
|
||||||
import { computed, watchEffect, defineComponent, ref, watch, toRaw } from 'vue';
|
import { computed, watchEffect, defineComponent, ref, watch, toRaw } from 'vue';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import { getPropsSlot } from '../_util/props-util';
|
import { getPropsSlot } from '../_util/props-util';
|
||||||
|
@ -8,7 +8,15 @@ import Operation from './operation';
|
||||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||||
import defaultLocale from '../locale/en_US';
|
import defaultLocale from '../locale/en_US';
|
||||||
import type { VueNode } from '../_util/type';
|
import type { VueNode } from '../_util/type';
|
||||||
import { withInstall } from '../_util/type';
|
import {
|
||||||
|
withInstall,
|
||||||
|
stringType,
|
||||||
|
arrayType,
|
||||||
|
someType,
|
||||||
|
booleanType,
|
||||||
|
objectType,
|
||||||
|
functionType,
|
||||||
|
} from '../_util/type';
|
||||||
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||||
import type { TransferListBodyProps } from './ListBody';
|
import type { TransferListBodyProps } from './ListBody';
|
||||||
import type { PaginationType } from './interface';
|
import type { PaginationType } from './interface';
|
||||||
|
@ -17,6 +25,9 @@ import type { RenderEmptyHandler } from '../config-provider/renderEmpty';
|
||||||
import type { InputStatus } from '../_util/statusUtils';
|
import type { InputStatus } from '../_util/statusUtils';
|
||||||
import { getStatusClassNames, getMergedStatus } from '../_util/statusUtils';
|
import { getStatusClassNames, getMergedStatus } from '../_util/statusUtils';
|
||||||
|
|
||||||
|
// CSSINJS
|
||||||
|
import useStyle from './style';
|
||||||
|
|
||||||
export type { TransferListProps } from './list';
|
export type { TransferListProps } from './list';
|
||||||
export type { TransferOperationProps } from './operation';
|
export type { TransferOperationProps } from './operation';
|
||||||
export type { TransferSearchProps } from './search';
|
export type { TransferSearchProps } from './search';
|
||||||
|
@ -69,40 +80,41 @@ export interface TransferLocale {
|
||||||
export const transferProps = () => ({
|
export const transferProps = () => ({
|
||||||
id: String,
|
id: String,
|
||||||
prefixCls: String,
|
prefixCls: String,
|
||||||
dataSource: { type: Array as PropType<TransferItem[]>, default: [] },
|
dataSource: arrayType<TransferItem[]>([]),
|
||||||
disabled: { type: Boolean, default: undefined },
|
disabled: booleanType(),
|
||||||
targetKeys: { type: Array as PropType<string[]>, default: undefined },
|
targetKeys: arrayType<string[]>(),
|
||||||
selectedKeys: { type: Array as PropType<string[]>, default: undefined },
|
selectedKeys: arrayType<string[]>(),
|
||||||
render: { type: Function as PropType<TransferRender<TransferItem>> },
|
render: functionType<TransferRender<TransferItem>>(),
|
||||||
listStyle: {
|
listStyle: someType<((style: ListStyle) => CSSProperties) | CSSProperties>(
|
||||||
type: [Function, Object] as PropType<((style: ListStyle) => CSSProperties) | CSSProperties>,
|
[Function, Object],
|
||||||
default: () => ({}),
|
() => ({}),
|
||||||
},
|
),
|
||||||
operationStyle: { type: Object as PropType<CSSProperties>, default: undefined as CSSProperties },
|
operationStyle: objectType<CSSProperties>(undefined as CSSProperties),
|
||||||
titles: { type: Array as PropType<string[]> },
|
titles: arrayType<string[]>(),
|
||||||
operations: { type: Array as PropType<string[]> },
|
operations: arrayType<string[]>(),
|
||||||
showSearch: { type: Boolean, default: false },
|
showSearch: booleanType(false),
|
||||||
filterOption: { type: Function as PropType<(inputValue: string, item: TransferItem) => boolean> },
|
filterOption: functionType<(inputValue: string, item: TransferItem) => boolean>(),
|
||||||
searchPlaceholder: String,
|
searchPlaceholder: String,
|
||||||
notFoundContent: PropTypes.any,
|
notFoundContent: PropTypes.any,
|
||||||
locale: { type: Object as PropType<Partial<TransferLocale>>, default: () => ({}) },
|
locale: objectType(),
|
||||||
rowKey: { type: Function as PropType<(record: TransferItem) => string> },
|
rowKey: functionType<(record: TransferItem) => string>(),
|
||||||
showSelectAll: { type: Boolean, default: undefined },
|
showSelectAll: booleanType(),
|
||||||
selectAllLabels: { type: Array as PropType<SelectAllLabel[]> },
|
selectAllLabels: arrayType<SelectAllLabel[]>(),
|
||||||
children: { type: Function as PropType<(props: TransferListBodyProps) => VueNode> },
|
children: functionType<(props: TransferListBodyProps) => VueNode>(),
|
||||||
oneWay: { type: Boolean, default: undefined },
|
oneWay: booleanType(),
|
||||||
pagination: { type: [Object, Boolean] as PropType<PaginationType>, default: undefined },
|
pagination: someType<PaginationType>([Object, Boolean]),
|
||||||
status: String as PropType<InputStatus>,
|
status: stringType<InputStatus>(),
|
||||||
onChange: Function as PropType<
|
onChange:
|
||||||
(targetKeys: string[], direction: TransferDirection, moveKeys: string[]) => void
|
functionType<
|
||||||
>,
|
(targetKeys: string[], direction: TransferDirection, moveKeys: string[]) => void
|
||||||
onSelectChange: Function as PropType<
|
>(),
|
||||||
|
onSelectChange: functionType<
|
||||||
(sourceSelectedKeys: string[], targetSelectedKeys: string[]) => void
|
(sourceSelectedKeys: string[], targetSelectedKeys: string[]) => void
|
||||||
>,
|
>,
|
||||||
onSearch: Function as PropType<(direction: TransferDirection, value: string) => void>,
|
onSearch: functionType<(direction: TransferDirection, value: string) => void>(),
|
||||||
onScroll: Function as PropType<(direction: TransferDirection, e: UIEvent) => void>,
|
onScroll: functionType<(direction: TransferDirection, e: UIEvent) => void>(),
|
||||||
'onUpdate:targetKeys': Function as PropType<(keys: string[]) => void>,
|
'onUpdate:targetKeys': functionType<(keys: string[]) => void>(),
|
||||||
'onUpdate:selectedKeys': Function as PropType<(keys: string[]) => void>,
|
'onUpdate:selectedKeys': functionType<(keys: string[]) => void>(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TransferProps = Partial<ExtractPropTypes<ReturnType<typeof transferProps>>>;
|
export type TransferProps = Partial<ExtractPropTypes<ReturnType<typeof transferProps>>>;
|
||||||
|
@ -125,6 +137,10 @@ const Transfer = defineComponent({
|
||||||
// emits: ['update:targetKeys', 'update:selectedKeys', 'change', 'search', 'scroll', 'selectChange'],
|
// emits: ['update:targetKeys', 'update:selectedKeys', 'change', 'search', 'scroll', 'selectChange'],
|
||||||
setup(props, { emit, attrs, slots, expose }) {
|
setup(props, { emit, attrs, slots, expose }) {
|
||||||
const { configProvider, prefixCls, direction } = useConfigInject('transfer', props);
|
const { configProvider, prefixCls, direction } = useConfigInject('transfer', props);
|
||||||
|
|
||||||
|
// style
|
||||||
|
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||||
|
|
||||||
const sourceSelectedKeys = ref([]);
|
const sourceSelectedKeys = ref([]);
|
||||||
const targetSelectedKeys = ref([]);
|
const targetSelectedKeys = ref([]);
|
||||||
|
|
||||||
|
@ -349,6 +365,7 @@ const Transfer = defineComponent({
|
||||||
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
||||||
},
|
},
|
||||||
getStatusClassNames(prefixCls.value, mergedStatus.value, formItemInputContext.hasFeedback),
|
getStatusClassNames(prefixCls.value, mergedStatus.value, formItemInputContext.hasFeedback),
|
||||||
|
hashId.value,
|
||||||
);
|
);
|
||||||
const titles = props.titles;
|
const titles = props.titles;
|
||||||
const leftTitle =
|
const leftTitle =
|
||||||
|
@ -356,7 +373,7 @@ const Transfer = defineComponent({
|
||||||
const rightTitle =
|
const rightTitle =
|
||||||
(titles && titles[1]) ?? slots.rightTitle?.() ?? (locale.titles || ['', ''])[1];
|
(titles && titles[1]) ?? slots.rightTitle?.() ?? (locale.titles || ['', ''])[1];
|
||||||
return (
|
return (
|
||||||
<div class={cls} style={style as CSSProperties} id={id}>
|
<div {...attrs} class={cls} style={style as CSSProperties} id={id}>
|
||||||
<List
|
<List
|
||||||
key="leftList"
|
key="leftList"
|
||||||
prefixCls={`${prefixCls.value}-list`}
|
prefixCls={`${prefixCls.value}-list`}
|
||||||
|
@ -422,13 +439,14 @@ const Transfer = defineComponent({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
return () => (
|
return () =>
|
||||||
<LocaleReceiver
|
wrapSSR(
|
||||||
componentName="Transfer"
|
<LocaleReceiver
|
||||||
defaultLocale={defaultLocale.Transfer}
|
componentName="Transfer"
|
||||||
children={renderTransfer}
|
defaultLocale={defaultLocale.Transfer}
|
||||||
/>
|
children={renderTransfer}
|
||||||
);
|
/>,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ category: Components
|
||||||
type: 数据录入
|
type: 数据录入
|
||||||
title: Transfer
|
title: Transfer
|
||||||
subtitle: 穿梭框
|
subtitle: 穿梭框
|
||||||
cover: https://gw.alipayobjects.com/zos/alicdn/QAXskNI4G/Transfer.svg
|
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*EAApQ5ephigAAAAAAAAAAAAADrJ8AQ/original
|
||||||
---
|
---
|
||||||
|
|
||||||
双栏穿梭选择框。
|
双栏穿梭选择框。
|
||||||
|
@ -32,6 +32,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/QAXskNI4G/Transfer.svg
|
||||||
| operationStyle | 操作栏的自定义样式 | CSSProperties | - | 3.0.0 |
|
| operationStyle | 操作栏的自定义样式 | CSSProperties | - | 3.0.0 |
|
||||||
| pagination | 使用分页样式,自定义渲染列表下无效 | boolean \| { pageSize: number, simple: boolean, showSizeChanger?: boolean, showLessItems?: boolean } | flase | 3.0.0 |
|
| pagination | 使用分页样式,自定义渲染列表下无效 | boolean \| { pageSize: number, simple: boolean, showSizeChanger?: boolean, showLessItems?: boolean } | flase | 3.0.0 |
|
||||||
| render | 每行数据渲染函数,该函数的入参为 `dataSource` 中的项,返回值为 element。或者返回一个普通对象,其中 `label` 字段为 element,`value` 字段为 title | Function(record)\| slot | | |
|
| render | 每行数据渲染函数,该函数的入参为 `dataSource` 中的项,返回值为 element。或者返回一个普通对象,其中 `label` 字段为 element,`value` 字段为 title | Function(record)\| slot | | |
|
||||||
|
| selectAllLabels | 自定义顶部多选框标题的集合 | VueNode \| ((info: { selectedCount: number; totalCount: number }) => VueNode); | - | 3.0.0 |
|
||||||
| selectedKeys(v-model) | 设置哪些项应该被选中 | string\[] | \[] | |
|
| selectedKeys(v-model) | 设置哪些项应该被选中 | string\[] | \[] | |
|
||||||
| showSearch | 是否显示搜索框 | boolean | false | |
|
| showSearch | 是否显示搜索框 | boolean | false | |
|
||||||
| showSelectAll | 是否展示全选勾选框 | boolean | true | |
|
| showSelectAll | 是否展示全选勾选框 | boolean | true | |
|
||||||
|
|
|
@ -7,10 +7,11 @@ import Menu from '../menu';
|
||||||
import Dropdown from '../dropdown';
|
import Dropdown from '../dropdown';
|
||||||
import Search from './search';
|
import Search from './search';
|
||||||
import ListBody from './ListBody';
|
import ListBody from './ListBody';
|
||||||
import type { VNode, VNodeTypes, ExtractPropTypes, PropType, CSSProperties } from 'vue';
|
import type { VNode, VNodeTypes, ExtractPropTypes, CSSProperties } from 'vue';
|
||||||
import { watchEffect, computed, defineComponent, ref } from 'vue';
|
import { watchEffect, computed, defineComponent, ref } from 'vue';
|
||||||
import type { RadioChangeEvent } from '../radio/interface';
|
import type { RadioChangeEvent } from '../radio/interface';
|
||||||
import type { TransferDirection, TransferItem } from './index';
|
import type { TransferDirection, TransferItem } from './index';
|
||||||
|
import { stringType, arrayType, booleanType } from '../_util/type';
|
||||||
|
|
||||||
const defaultRender = () => null;
|
const defaultRender = () => null;
|
||||||
|
|
||||||
|
@ -28,22 +29,22 @@ function getEnabledItemKeys<RecordType extends TransferItem>(items: RecordType[]
|
||||||
|
|
||||||
export const transferListProps = {
|
export const transferListProps = {
|
||||||
prefixCls: String,
|
prefixCls: String,
|
||||||
dataSource: { type: Array as PropType<TransferItem[]>, default: [] },
|
dataSource: arrayType<TransferItem[]>([]),
|
||||||
filter: String,
|
filter: String,
|
||||||
filterOption: Function,
|
filterOption: Function,
|
||||||
checkedKeys: PropTypes.arrayOf(PropTypes.string),
|
checkedKeys: PropTypes.arrayOf(PropTypes.string),
|
||||||
handleFilter: Function,
|
handleFilter: Function,
|
||||||
handleClear: Function,
|
handleClear: Function,
|
||||||
renderItem: Function,
|
renderItem: Function,
|
||||||
showSearch: { type: Boolean, default: false },
|
showSearch: booleanType(false),
|
||||||
searchPlaceholder: String,
|
searchPlaceholder: String,
|
||||||
notFoundContent: PropTypes.any,
|
notFoundContent: PropTypes.any,
|
||||||
itemUnit: String,
|
itemUnit: String,
|
||||||
itemsUnit: String,
|
itemsUnit: String,
|
||||||
renderList: PropTypes.any,
|
renderList: PropTypes.any,
|
||||||
disabled: { type: Boolean, default: undefined },
|
disabled: booleanType(),
|
||||||
direction: String as PropType<TransferDirection>,
|
direction: stringType<TransferDirection>(),
|
||||||
showSelectAll: { type: Boolean, default: undefined },
|
showSelectAll: booleanType(),
|
||||||
remove: String,
|
remove: String,
|
||||||
selectAll: String,
|
selectAll: String,
|
||||||
selectCurrent: String,
|
selectCurrent: String,
|
||||||
|
@ -51,7 +52,7 @@ export const transferListProps = {
|
||||||
removeAll: String,
|
removeAll: String,
|
||||||
removeCurrent: String,
|
removeCurrent: String,
|
||||||
selectAllLabel: PropTypes.any,
|
selectAllLabel: PropTypes.any,
|
||||||
showRemove: { type: Boolean, default: undefined },
|
showRemove: booleanType(),
|
||||||
pagination: PropTypes.any,
|
pagination: PropTypes.any,
|
||||||
onItemSelect: Function,
|
onItemSelect: Function,
|
||||||
onItemSelectAll: Function,
|
onItemSelectAll: Function,
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
@import '../../style/themes/index';
|
|
||||||
|
|
||||||
@transfer-prefix-cls: ~'@{ant-prefix}-transfer';
|
|
||||||
|
|
||||||
@table-prefix-cls: ~'@{ant-prefix}-table';
|
|
||||||
@input-prefix-cls: ~'@{ant-prefix}-input';
|
|
||||||
|
|
||||||
.@{transfer-prefix-cls}-customize-list {
|
|
||||||
.@{transfer-prefix-cls}-list {
|
|
||||||
flex: 1 1 50%;
|
|
||||||
width: auto;
|
|
||||||
height: auto;
|
|
||||||
min-height: @transfer-list-height;
|
|
||||||
}
|
|
||||||
|
|
||||||
// =================== Hook Components ===================
|
|
||||||
.@{table-prefix-cls}-wrapper {
|
|
||||||
.@{table-prefix-cls}-small {
|
|
||||||
border: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
|
|
||||||
.@{table-prefix-cls}-selection-column {
|
|
||||||
width: 40px;
|
|
||||||
min-width: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .@{table-prefix-cls}-content {
|
|
||||||
// Header background color
|
|
||||||
> .@{table-prefix-cls}-body > table > .@{table-prefix-cls}-thead > tr > th {
|
|
||||||
background: @table-header-bg;
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{table-prefix-cls}-row:last-child td {
|
|
||||||
border-bottom: @border-width-base @border-style-base @border-color-split;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{table-prefix-cls}-body {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{table-prefix-cls}-pagination.@{ant-prefix}-pagination {
|
|
||||||
margin: 16px 0 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.@{input-prefix-cls} {
|
|
||||||
&[disabled] {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,221 +0,0 @@
|
||||||
@import '../../style/themes/index';
|
|
||||||
@import '../../style/mixins/index';
|
|
||||||
@import '../../checkbox/style/mixin';
|
|
||||||
@import './customize';
|
|
||||||
@import './status';
|
|
||||||
|
|
||||||
@transfer-prefix-cls: ~'@{ant-prefix}-transfer';
|
|
||||||
|
|
||||||
@transfer-header-vertical-padding: ceil(
|
|
||||||
((@transfer-header-height - 1px - @font-size-base * @line-height-base) / 2)
|
|
||||||
);
|
|
||||||
|
|
||||||
.@{transfer-prefix-cls} {
|
|
||||||
.reset-component();
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: stretch;
|
|
||||||
|
|
||||||
&-disabled {
|
|
||||||
.@{transfer-prefix-cls}-list {
|
|
||||||
background: @transfer-disabled-bg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 180px;
|
|
||||||
height: @transfer-list-height;
|
|
||||||
border: @border-width-base @border-style-base @border-color-base;
|
|
||||||
border-radius: @border-radius-base;
|
|
||||||
|
|
||||||
&-with-pagination {
|
|
||||||
width: 250px;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-search {
|
|
||||||
.anticon-search {
|
|
||||||
color: @disabled-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-header {
|
|
||||||
display: flex;
|
|
||||||
flex: none;
|
|
||||||
align-items: center;
|
|
||||||
height: @transfer-header-height;
|
|
||||||
// border-top is on the transfer dom. We should minus 1px for this
|
|
||||||
padding: (@transfer-header-vertical-padding - 1px) @control-padding-horizontal
|
|
||||||
@transfer-header-vertical-padding;
|
|
||||||
color: @text-color;
|
|
||||||
background: @component-background;
|
|
||||||
border-bottom: @border-width-base @border-style-base @border-color-split;
|
|
||||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
|
||||||
|
|
||||||
> *:not(:last-child) {
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> * {
|
|
||||||
flex: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-title {
|
|
||||||
flex: auto;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-align: right;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-dropdown {
|
|
||||||
font-size: 10px;
|
|
||||||
transform: translateY(10%);
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&[disabled] {
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-body {
|
|
||||||
display: flex;
|
|
||||||
flex: auto;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: @font-size-base;
|
|
||||||
|
|
||||||
&-search-wrapper {
|
|
||||||
position: relative;
|
|
||||||
flex: none;
|
|
||||||
padding: @padding-sm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-content {
|
|
||||||
flex: auto;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
overflow: auto;
|
|
||||||
list-style: none;
|
|
||||||
|
|
||||||
&-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
min-height: @transfer-item-height;
|
|
||||||
padding: @transfer-item-padding-vertical @control-padding-horizontal;
|
|
||||||
line-height: @transfer-item-height - 2 * @transfer-item-padding-vertical;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
> *:not(:last-child) {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> * {
|
|
||||||
flex: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-text {
|
|
||||||
flex: auto;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-remove {
|
|
||||||
.operation-unit();
|
|
||||||
position: relative;
|
|
||||||
color: @border-color-base;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
position: absolute;
|
|
||||||
top: -@transfer-item-padding-vertical;
|
|
||||||
right: -50%;
|
|
||||||
bottom: -@transfer-item-padding-vertical;
|
|
||||||
left: -50%;
|
|
||||||
content: '';
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: @link-hover-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-item:not(&-item-disabled) {
|
|
||||||
&:hover {
|
|
||||||
background-color: @transfer-item-hover-bg;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.@{transfer-prefix-cls}-list-content-item-checked:hover {
|
|
||||||
background-color: @transfer-item-selected-hover-bg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not change hover style when `oneWay` mode
|
|
||||||
&-show-remove &-item:not(&-item-disabled):hover {
|
|
||||||
background: transparent;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-item-checked {
|
|
||||||
background-color: @item-active-bg;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-item-disabled {
|
|
||||||
color: @btn-disable-color;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-pagination {
|
|
||||||
padding: @padding-xs 0;
|
|
||||||
text-align: right;
|
|
||||||
border-top: @border-width-base @border-style-base @border-color-split;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-body-not-found {
|
|
||||||
flex: none;
|
|
||||||
width: 100%;
|
|
||||||
margin: auto 0;
|
|
||||||
color: @disabled-color;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-footer {
|
|
||||||
border-top: @border-width-base @border-style-base @border-color-split;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-operation {
|
|
||||||
display: flex;
|
|
||||||
flex: none;
|
|
||||||
flex-direction: column;
|
|
||||||
align-self: center;
|
|
||||||
margin: 0 8px;
|
|
||||||
vertical-align: middle;
|
|
||||||
|
|
||||||
.@{ant-prefix}-btn {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{iconfont-css-prefix} {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{ant-prefix}-empty-image {
|
|
||||||
max-height: (@transfer-header-height / 2) - 22;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@import './rtl';
|
|
|
@ -1,13 +1,373 @@
|
||||||
import '../../style/index.less';
|
import type { CSSObject } from '../../_util/cssinjs';
|
||||||
import './index.less';
|
|
||||||
|
|
||||||
// style dependencies
|
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||||
import '../../empty/style';
|
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||||
import '../../checkbox/style';
|
import { resetComponent, resetIcon, textEllipsis } from '../../_style';
|
||||||
import '../../button/style';
|
|
||||||
import '../../input/style';
|
|
||||||
import '../../menu/style';
|
|
||||||
import '../../dropdown/style';
|
|
||||||
import '../../pagination/style';
|
|
||||||
|
|
||||||
// deps-lint-skip: form
|
export interface ComponentToken {
|
||||||
|
listWidth: number;
|
||||||
|
listWidthLG: number;
|
||||||
|
listHeight: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TransferToken extends FullToken<'Transfer'> {
|
||||||
|
transferItemHeight: number;
|
||||||
|
transferHeaderVerticalPadding: number;
|
||||||
|
transferItemPaddingVertical: number;
|
||||||
|
transferHeaderHeight: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const genTransferCustomizeStyle: GenerateStyle<TransferToken> = (
|
||||||
|
token: TransferToken,
|
||||||
|
): CSSObject => {
|
||||||
|
const { antCls, componentCls, listHeight, controlHeightLG, marginXXS, margin } = token;
|
||||||
|
|
||||||
|
const tableCls = `${antCls}-table`;
|
||||||
|
const inputCls = `${antCls}-input`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
[`${componentCls}-customize-list`]: {
|
||||||
|
[`${componentCls}-list`]: {
|
||||||
|
flex: '1 1 50%',
|
||||||
|
width: 'auto',
|
||||||
|
height: 'auto',
|
||||||
|
minHeight: listHeight,
|
||||||
|
},
|
||||||
|
|
||||||
|
// =================== Hook Components ===================
|
||||||
|
[`${tableCls}-wrapper`]: {
|
||||||
|
[`${tableCls}-small`]: {
|
||||||
|
border: 0,
|
||||||
|
borderRadius: 0,
|
||||||
|
|
||||||
|
[`${tableCls}-selection-column`]: {
|
||||||
|
width: controlHeightLG,
|
||||||
|
minWidth: controlHeightLG,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${tableCls}-pagination${tableCls}-pagination`]: {
|
||||||
|
margin: `${margin}px 0 ${marginXXS}px`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${inputCls}[disabled]`]: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const genTransferStatusColor = (token: TransferToken, color: string): CSSObject => {
|
||||||
|
const { componentCls, colorBorder } = token;
|
||||||
|
return {
|
||||||
|
[`${componentCls}-list`]: {
|
||||||
|
borderColor: color,
|
||||||
|
|
||||||
|
'&-search:not([disabled])': {
|
||||||
|
borderColor: colorBorder,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const genTransferStatusStyle: GenerateStyle<TransferToken> = (token: TransferToken): CSSObject => {
|
||||||
|
const { componentCls } = token;
|
||||||
|
return {
|
||||||
|
[`${componentCls}-status-error`]: {
|
||||||
|
...genTransferStatusColor(token, token.colorError),
|
||||||
|
},
|
||||||
|
[`${componentCls}-status-warning`]: {
|
||||||
|
...genTransferStatusColor(token, token.colorWarning),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const genTransferListStyle: GenerateStyle<TransferToken> = (token: TransferToken): CSSObject => {
|
||||||
|
const {
|
||||||
|
componentCls,
|
||||||
|
colorBorder,
|
||||||
|
colorSplit,
|
||||||
|
lineWidth,
|
||||||
|
transferItemHeight,
|
||||||
|
transferHeaderHeight,
|
||||||
|
transferHeaderVerticalPadding,
|
||||||
|
transferItemPaddingVertical,
|
||||||
|
controlItemBgActive,
|
||||||
|
controlItemBgActiveHover,
|
||||||
|
colorTextDisabled,
|
||||||
|
listHeight,
|
||||||
|
listWidth,
|
||||||
|
listWidthLG,
|
||||||
|
fontSizeIcon,
|
||||||
|
marginXS,
|
||||||
|
paddingSM,
|
||||||
|
lineType,
|
||||||
|
iconCls,
|
||||||
|
motionDurationSlow,
|
||||||
|
} = token;
|
||||||
|
|
||||||
|
return {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
width: listWidth,
|
||||||
|
height: listHeight,
|
||||||
|
border: `${lineWidth}px ${lineType} ${colorBorder}`,
|
||||||
|
borderRadius: token.borderRadiusLG,
|
||||||
|
|
||||||
|
'&-with-pagination': {
|
||||||
|
width: listWidthLG,
|
||||||
|
height: 'auto',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-search': {
|
||||||
|
[`${iconCls}-search`]: {
|
||||||
|
color: colorTextDisabled,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-header': {
|
||||||
|
display: 'flex',
|
||||||
|
flex: 'none',
|
||||||
|
alignItems: 'center',
|
||||||
|
height: transferHeaderHeight,
|
||||||
|
// border-top is on the transfer dom. We should minus 1px for this
|
||||||
|
padding: `${
|
||||||
|
transferHeaderVerticalPadding - lineWidth
|
||||||
|
}px ${paddingSM}px ${transferHeaderVerticalPadding}px`,
|
||||||
|
color: token.colorText,
|
||||||
|
background: token.colorBgContainer,
|
||||||
|
borderBottom: `${lineWidth}px ${lineType} ${colorSplit}`,
|
||||||
|
borderRadius: `${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0`,
|
||||||
|
|
||||||
|
'> *:not(:last-child)': {
|
||||||
|
marginInlineEnd: 4, // This is magic and fixed number, DO NOT use token since it may change.
|
||||||
|
},
|
||||||
|
|
||||||
|
'> *': {
|
||||||
|
flex: 'none',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-title': {
|
||||||
|
...textEllipsis,
|
||||||
|
flex: 'auto',
|
||||||
|
textAlign: 'end',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-dropdown': {
|
||||||
|
...resetIcon(),
|
||||||
|
|
||||||
|
fontSize: fontSizeIcon,
|
||||||
|
transform: 'translateY(10%)',
|
||||||
|
cursor: 'pointer',
|
||||||
|
|
||||||
|
'&[disabled]': {
|
||||||
|
cursor: 'not-allowed',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-body': {
|
||||||
|
display: 'flex',
|
||||||
|
flex: 'auto',
|
||||||
|
flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
fontSize: token.fontSize,
|
||||||
|
|
||||||
|
'&-search-wrapper': {
|
||||||
|
position: 'relative',
|
||||||
|
flex: 'none',
|
||||||
|
padding: paddingSM,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-content': {
|
||||||
|
flex: 'auto',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
overflow: 'auto',
|
||||||
|
listStyle: 'none',
|
||||||
|
|
||||||
|
'&-item': {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
minHeight: transferItemHeight,
|
||||||
|
padding: `${transferItemPaddingVertical}px ${paddingSM}px`,
|
||||||
|
transition: `all ${motionDurationSlow}`,
|
||||||
|
|
||||||
|
'> *:not(:last-child)': {
|
||||||
|
marginInlineEnd: marginXS,
|
||||||
|
},
|
||||||
|
|
||||||
|
'> *': {
|
||||||
|
flex: 'none',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-text': {
|
||||||
|
...textEllipsis,
|
||||||
|
flex: 'auto',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-remove': {
|
||||||
|
position: 'relative',
|
||||||
|
color: colorBorder,
|
||||||
|
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: `all ${motionDurationSlow}`,
|
||||||
|
|
||||||
|
'&:hover': {
|
||||||
|
color: token.colorLinkHover,
|
||||||
|
},
|
||||||
|
|
||||||
|
'&::after': {
|
||||||
|
position: 'absolute',
|
||||||
|
insert: `-${transferItemPaddingVertical}px -50%`,
|
||||||
|
content: '""',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&:not(${componentCls}-list-content-item-disabled)`]: {
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: token.controlItemBgHover,
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&${componentCls}-list-content-item-checked:hover`]: {
|
||||||
|
backgroundColor: controlItemBgActiveHover,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-checked': {
|
||||||
|
backgroundColor: controlItemBgActive,
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-disabled': {
|
||||||
|
color: colorTextDisabled,
|
||||||
|
cursor: 'not-allowed',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Do not change hover style when `oneWay` mode
|
||||||
|
[`&-show-remove ${componentCls}-list-content-item:not(${componentCls}-list-content-item-disabled):hover`]:
|
||||||
|
{
|
||||||
|
background: 'transparent',
|
||||||
|
cursor: 'default',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-pagination': {
|
||||||
|
padding: `${token.paddingXS}px 0`,
|
||||||
|
textAlign: 'end',
|
||||||
|
borderTop: `${lineWidth}px ${lineType} ${colorSplit}`,
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-body-not-found': {
|
||||||
|
flex: 'none',
|
||||||
|
width: '100%',
|
||||||
|
margin: 'auto 0',
|
||||||
|
color: colorTextDisabled,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-footer': {
|
||||||
|
borderTop: `${lineWidth}px ${lineType} ${colorSplit}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const genTransferStyle: GenerateStyle<TransferToken> = (token: TransferToken): CSSObject => {
|
||||||
|
const {
|
||||||
|
antCls,
|
||||||
|
iconCls,
|
||||||
|
componentCls,
|
||||||
|
transferHeaderHeight,
|
||||||
|
marginXS,
|
||||||
|
marginXXS,
|
||||||
|
fontSizeIcon,
|
||||||
|
fontSize,
|
||||||
|
lineHeight,
|
||||||
|
} = token;
|
||||||
|
|
||||||
|
return {
|
||||||
|
[componentCls]: {
|
||||||
|
...resetComponent(token),
|
||||||
|
|
||||||
|
position: 'relative',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'stretch',
|
||||||
|
|
||||||
|
[`${componentCls}-disabled`]: {
|
||||||
|
[`${componentCls}-list`]: {
|
||||||
|
background: token.colorBgContainerDisabled,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${componentCls}-list`]: genTransferListStyle(token),
|
||||||
|
|
||||||
|
[`${componentCls}-operation`]: {
|
||||||
|
display: 'flex',
|
||||||
|
flex: 'none',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignSelf: 'center',
|
||||||
|
margin: `0 ${marginXS}px`,
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
|
||||||
|
[`${antCls}-btn`]: {
|
||||||
|
display: 'block',
|
||||||
|
|
||||||
|
'&:first-child': {
|
||||||
|
marginBottom: marginXXS,
|
||||||
|
},
|
||||||
|
|
||||||
|
[iconCls]: {
|
||||||
|
fontSize: fontSizeIcon,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${antCls}-empty-image`]: {
|
||||||
|
maxHeight: transferHeaderHeight / 2 - Math.round(fontSize * lineHeight),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const genTransferRTLStyle: GenerateStyle<TransferToken> = (token: TransferToken): CSSObject => {
|
||||||
|
const { componentCls } = token;
|
||||||
|
return {
|
||||||
|
[`${componentCls}-rtl`]: {
|
||||||
|
direction: 'rtl',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================== Export ==============================
|
||||||
|
export default genComponentStyleHook(
|
||||||
|
'Transfer',
|
||||||
|
token => {
|
||||||
|
const { fontSize, lineHeight, lineWidth, controlHeightLG, controlHeight } = token;
|
||||||
|
|
||||||
|
const fontHeight = Math.round(fontSize * lineHeight);
|
||||||
|
const transferHeaderHeight = controlHeightLG;
|
||||||
|
const transferItemHeight = controlHeight;
|
||||||
|
|
||||||
|
const transferToken = mergeToken<TransferToken>(token, {
|
||||||
|
transferItemHeight,
|
||||||
|
transferHeaderHeight,
|
||||||
|
transferHeaderVerticalPadding: Math.ceil((transferHeaderHeight - lineWidth - fontHeight) / 2),
|
||||||
|
transferItemPaddingVertical: (transferItemHeight - fontHeight) / 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
return [
|
||||||
|
genTransferStyle(transferToken),
|
||||||
|
genTransferCustomizeStyle(transferToken),
|
||||||
|
genTransferStatusStyle(transferToken),
|
||||||
|
genTransferRTLStyle(transferToken),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
{
|
||||||
|
listWidth: 180,
|
||||||
|
listHeight: 200,
|
||||||
|
listWidthLG: 250,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
@import '../../style/themes/index';
|
|
||||||
@import '../../style/mixins/index';
|
|
||||||
@import '../../checkbox/style/mixin';
|
|
||||||
|
|
||||||
@transfer-prefix-cls: ~'@{ant-prefix}-transfer';
|
|
||||||
|
|
||||||
.@{transfer-prefix-cls} {
|
|
||||||
&-rtl {
|
|
||||||
direction: rtl;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-list {
|
|
||||||
&-search {
|
|
||||||
.@{transfer-prefix-cls}-rtl & {
|
|
||||||
padding-right: @control-padding-horizontal-sm;
|
|
||||||
padding-left: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-action {
|
|
||||||
.@{transfer-prefix-cls}-rtl & {
|
|
||||||
right: auto;
|
|
||||||
left: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-header {
|
|
||||||
> *:not(:last-child) {
|
|
||||||
.@{transfer-prefix-cls}-rtl & {
|
|
||||||
margin-right: 0;
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{transfer-prefix-cls}-rtl & {
|
|
||||||
right: 0;
|
|
||||||
left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-title {
|
|
||||||
.@{transfer-prefix-cls}-rtl & {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-content {
|
|
||||||
&-item {
|
|
||||||
> *:not(:last-child) {
|
|
||||||
.@{transfer-prefix-cls}-rtl & {
|
|
||||||
margin-right: 0;
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-pagination {
|
|
||||||
.@{transfer-prefix-cls}-rtl & {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-footer {
|
|
||||||
.@{transfer-prefix-cls}-rtl & {
|
|
||||||
right: 0;
|
|
||||||
left: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
@import '../../input/style/mixin';
|
|
||||||
|
|
||||||
@transfer-prefix-cls: ~'@{ant-prefix}-transfer';
|
|
||||||
|
|
||||||
.transfer-status-color(@color) {
|
|
||||||
.@{transfer-prefix-cls}-list {
|
|
||||||
border-color: @color;
|
|
||||||
|
|
||||||
&-search:not([disabled]) {
|
|
||||||
border-color: @input-border-color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.hover();
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
.active();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{transfer-prefix-cls} {
|
|
||||||
&-status-error {
|
|
||||||
.transfer-status-color(@error-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&-status-warning {
|
|
||||||
.transfer-status-color(@warning-color);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue