diff --git a/src/transfer/index.ts b/src/transfer/index.ts index e88f3d561..179574151 100644 --- a/src/transfer/index.ts +++ b/src/transfer/index.ts @@ -1,2 +1,2 @@ -/* istanbul ignore file */ export { default as NTransfer } from './src/Transfer' +export type { TransferProps } from './src/Transfer' diff --git a/src/transfer/src/Transfer.tsx b/src/transfer/src/Transfer.tsx index c998d4a1a..fe0b6136d 100644 --- a/src/transfer/src/Transfer.tsx +++ b/src/transfer/src/Transfer.tsx @@ -13,10 +13,10 @@ import { depx } from 'seemly' import { ChevronLeftIcon, ChevronRightIcon } from '../../_internal/icons' import { NBaseIcon } from '../../_internal' import { NButton } from '../../button' -import { useLocale, useFormItem, useTheme } from '../../_mixins' +import { useLocale, useFormItem, useTheme, useConfig } from '../../_mixins' import type { ThemeProps } from '../../_mixins' import { createKey } from '../../_utils/cssr' -import { warn, call } from '../../_utils' +import { warn, call, ExtractPublicPropTypes } from '../../_utils' import type { MaybeArray } from '../../_utils' import { transferLight } from '../styles' import type { TransferTheme } from '../styles' @@ -30,75 +30,81 @@ import { Option, Filter, OnUpdateValue, - TransferInjection + transferInjectionKey } from './interface' +const transferProps = { + ...(useTheme.props as ThemeProps), + value: Array as PropType, + defaultValue: { + type: Array as PropType, + default: null + }, + options: { + type: Array as PropType, + default: () => [] + }, + disabled: { + type: Boolean, + default: false + }, + virtualScroll: { + type: Boolean, + default: false + }, + sourceTitle: String, + targetTitle: String, + filterable: { + type: Boolean, + default: false + }, + sourceFilterPlaceholder: String, + targetFilterPlaceholder: String, + filter: { + type: Function as PropType, + default: (pattern: string, option: Option) => { + if (!pattern) return true + return ~('' + option.label) + .toLowerCase() + .indexOf(('' + pattern).toLowerCase()) + } + }, + size: { + type: String as PropType<'small' | 'medium' | 'large' | undefined>, + default: undefined + }, + // eslint-disable-next-line vue/prop-name-casing + 'onUpdate:value': [Function, Array] as PropType>, + onUpdateValue: [Function, Array] as PropType>, + onChange: { + type: [Function, Array] as PropType>, + validator: () => { + if (__DEV__) { + warn( + 'transfer', + '`on-change` is deprecated, please use `on-update:value` instead.' + ) + } + return true + }, + default: undefined + } +} as const + +export type TransferProps = ExtractPublicPropTypes + export default defineComponent({ name: 'Transfer', - props: { - ...(useTheme.props as ThemeProps), - value: Array as PropType, - defaultValue: { - type: Array as PropType, - default: null - }, - options: { - type: Array as PropType, - default: () => [] - }, - disabled: { - type: Boolean, - default: false - }, - virtualScroll: { - type: Boolean, - default: false - }, - sourceTitle: String, - targetTitle: String, - filterable: { - type: Boolean, - default: false - }, - sourceFilterPlaceholder: String, - targetFilterPlaceholder: String, - filter: { - type: Function as PropType, - default: (pattern: string, option: Option) => { - if (!pattern) return true - return ~('' + option.label) - .toLowerCase() - .indexOf(('' + pattern).toLowerCase()) - } - }, - size: { - type: String as PropType<'small' | 'medium' | 'large' | undefined>, - default: undefined - }, - // eslint-disable-next-line vue/prop-name-casing - 'onUpdate:value': [Function, Array] as PropType>, - onUpdateValue: [Function, Array] as PropType>, - onChange: { - type: [Function, Array] as PropType>, - validator: () => { - if (__DEV__) { - warn( - 'transfer', - '`on-change` is deprecated, please use `on-update:value` instead.' - ) - } - return true - }, - default: undefined - } - }, + props: transferProps, setup (props) { + const { mergedClsPrefix } = useConfig(props) const themeRef = useTheme( 'Transfer', 'Transfer', style, transferLight, - props + props, + mergedClsPrefix ) const formItem = useFormItem(props) const itemSizeRef = computed(() => { @@ -210,9 +216,10 @@ export default defineComponent({ ) tgtCheckedValuesRef.value = [] } - provide( - 'NTransfer', + provide( + transferInjectionKey, reactive({ + cPrefix: mergedClsPrefix, mergedSize: formItem.mergedSize, disabled: toRef(props, 'disabled'), mergedTheme: themeRef, @@ -229,6 +236,7 @@ export default defineComponent({ return { ...formItem, ...useLocale('Transfer'), + cPrefix: mergedClsPrefix, itemSize: itemSizeRef, isMounted: useIsMounted(), isInputing: isInputingRef, @@ -305,24 +313,23 @@ export default defineComponent({ } }, render () { + const { cPrefix } = this return (
-
+
-
+
{this.filterable ? ( ) : null} -
+
-
+
-
+
{{ icon: () => ( - {{ default: () => }} + + {{ default: () => }} + ) }} @@ -368,17 +377,19 @@ export default defineComponent({ > {{ icon: () => ( - {{ default: () => }} + + {{ default: () => }} + ) }}
-
+
-
+
{this.filterable ? ( ) : null} -
+
-
+
) diff --git a/src/transfer/src/TransferFilter.tsx b/src/transfer/src/TransferFilter.tsx index 93659645b..963032c0a 100644 --- a/src/transfer/src/TransferFilter.tsx +++ b/src/transfer/src/TransferFilter.tsx @@ -2,7 +2,7 @@ import { h, defineComponent, inject, PropType } from 'vue' import { SearchIcon } from '../../_internal/icons' import { NBaseIcon } from '../../_internal' import { NInput } from '../../input' -import { TransferInjection } from './interface' +import { transferInjectionKey } from './interface' export default defineComponent({ name: 'TransferFilter', @@ -24,23 +24,23 @@ export default defineComponent({ } }, setup () { - const NTransfer = inject( - 'NTransfer' - ) as TransferInjection + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const NTransfer = inject(transferInjectionKey)! return { NTransfer } }, render () { const { NTransfer } = this + const { mergedTheme, cPrefix } = NTransfer return ( -
+
{{ clear: () => ( - + {{ default: () => }} ) diff --git a/src/transfer/src/TransferHeader.tsx b/src/transfer/src/TransferHeader.tsx index fff14c426..0604bb80e 100644 --- a/src/transfer/src/TransferHeader.tsx +++ b/src/transfer/src/TransferHeader.tsx @@ -1,6 +1,6 @@ import { h, computed, defineComponent, inject, PropType } from 'vue' import { NCheckbox } from '../../checkbox' -import { TransferInjection } from './interface' +import { transferInjectionKey } from './interface' export default defineComponent({ name: 'TransferHeader', @@ -16,9 +16,8 @@ export default defineComponent({ title: String }, setup (props) { - const NTransfer = inject( - 'NTransfer' - ) as TransferInjection + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const NTransfer = inject(transferInjectionKey)! const checkboxPropsRef = computed(() => { const { source } = props if (source) { @@ -30,20 +29,23 @@ export default defineComponent({ return () => { const { source } = props const { value: checkboxProps } = checkboxPropsRef + const { mergedTheme, cPrefix } = NTransfer return ( -
-
+
+
-
{props.title}
-
+
+ {props.title} +
+
{source ? NTransfer.srcCheckedValues.length : NTransfer.tgtCheckedValues.length} diff --git a/src/transfer/src/TransferList.tsx b/src/transfer/src/TransferList.tsx index 36a86bc47..baee804c5 100644 --- a/src/transfer/src/TransferList.tsx +++ b/src/transfer/src/TransferList.tsx @@ -10,7 +10,7 @@ import { import { VirtualList, VirtualListRef } from 'vueuc' import { NEmpty } from '../../empty' import { NScrollbar, ScrollbarInst } from '../../scrollbar' -import type { Option, TransferInjection } from './interface' +import { Option, transferInjectionKey } from './interface' import NTransferListItem from './TransferListItem' export default defineComponent({ @@ -46,9 +46,8 @@ export default defineComponent({ } }, setup () { - const NTransfer = inject( - 'NTransfer' - ) as TransferInjection + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const NTransfer = inject(transferInjectionKey)! const scrollerInstRef = ref(null) const vlInstRef = ref(null) function syncVLScroller (): void { @@ -77,12 +76,13 @@ export default defineComponent({ }, render () { const { NTransfer, syncVLScroller } = this + const { mergedTheme, cPrefix } = NTransfer return this.options.length ? ( this.virtualScroll ? ( @@ -90,7 +90,8 @@ export default defineComponent({ default: () => ( {{ default: () => ( -
+
( - 'NTransfer' - ) as TransferInjection + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const NTransfer = inject(transferInjectionKey)! const checkedRef = source ? useMemo(() => NTransfer.srcCheckedValues.includes(props.value)) : useMemo(() => NTransfer.tgtCheckedValues.includes(props.value)) @@ -45,34 +44,32 @@ export default defineComponent({ return { NTransfer, checked: checkedRef, - className: source - ? 'n-transfer-list-item--source' - : 'n-transfer-list-item--target', handleClick } }, render () { - const { disabled, NTransfer, label, checked, className } = this + const { disabled, NTransfer, label, checked, source } = this + const { mergedTheme, cPrefix } = NTransfer return (
-
+
-
{label}
+
{label}
) } diff --git a/src/transfer/src/interface.ts b/src/transfer/src/interface.ts index 979fab66e..c27e1aa48 100644 --- a/src/transfer/src/interface.ts +++ b/src/transfer/src/interface.ts @@ -1,3 +1,4 @@ +import { InjectionKey } from 'vue' import type { MergedTheme } from '../../_mixins' import type { TransferTheme } from '../styles' @@ -21,6 +22,7 @@ export type Filter = ( ) => boolean export interface TransferInjection { + cPrefix: string mergedSize: 'small' | 'medium' | 'large' disabled: boolean mergedTheme: MergedTheme @@ -34,4 +36,8 @@ export interface TransferInjection { handleTgtCheckboxClick: (checked: boolean, value: OptionValue) => void } +export const transferInjectionKey: InjectionKey = Symbol( + 'transfer' +) + export type OnUpdateValue = (value: OptionValue[]) => void diff --git a/src/transfer/src/styles/index.cssr.ts b/src/transfer/src/styles/index.cssr.ts index ba69a0b58..b666ae69b 100644 --- a/src/transfer/src/styles/index.cssr.ts +++ b/src/transfer/src/styles/index.cssr.ts @@ -82,16 +82,6 @@ export default c([ border-radius: var(--border-radius); background-color: var(--list-color); `, [ - cB('virtual-scroller', { - height: '100%', - scrollbarWidth: 'none', - '-moz-scrollbar-width': 'none' - }, [ - c('&::-webkit-scrollbar', { - width: 0, - height: 0 - }) - ]), cE('border', ` border: 1px solid var(--border-color); transition: border-color .3s var(--bezier);