types(DropdownMenu): use tsx (#8167)

This commit is contained in:
neverland 2021-02-16 13:20:05 +08:00 committed by GitHub
parent 6c89575946
commit 8568c02e0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 20 deletions

View File

@ -1,8 +1,14 @@
import { reactive, Teleport } from 'vue'; import {
reactive,
Teleport,
PropType,
TeleportProps,
CSSProperties,
} from 'vue';
// Utils // Utils
import { createNamespace, UnknownProp } from '../utils'; import { createNamespace, UnknownProp } from '../utils';
import { DROPDOWN_KEY } from '../dropdown-menu'; import { DROPDOWN_KEY, DropdownMenuProvide } from '../dropdown-menu';
// Composition // Composition
import { useParent } from '@vant/use'; import { useParent } from '@vant/use';
@ -15,15 +21,21 @@ import Popup from '../popup';
const [createComponent, bem] = createNamespace('dropdown-item'); const [createComponent, bem] = createNamespace('dropdown-item');
export type DropdownItemOption = {
text: string;
icon?: string;
value: number | string;
};
export default createComponent({ export default createComponent({
props: { props: {
title: String, title: String,
disabled: Boolean, disabled: Boolean,
teleport: [String, Object], teleport: [String, Object] as PropType<TeleportProps['to']>,
modelValue: UnknownProp, modelValue: UnknownProp,
titleClass: UnknownProp, titleClass: UnknownProp,
options: { options: {
type: Array, type: Array as PropType<DropdownItemOption[]>,
default: () => [], default: () => [],
}, },
lazyRender: { lazyRender: {
@ -41,9 +53,19 @@ export default createComponent({
showWrapper: false, showWrapper: false,
}); });
const { parent } = useParent(DROPDOWN_KEY); const { parent } = useParent<DropdownMenuProvide>(DROPDOWN_KEY);
const createEmitter = (eventName) => () => emit(eventName); if (!parent) {
if (process.env.NODE_ENV !== 'production') {
console.error(
'[Vant] DropdownItem must be a child component of DropdownMenu.'
);
}
return;
}
const createEmitter = (eventName: 'open' | 'close' | 'opened') => () =>
emit(eventName);
const onOpen = createEmitter('open'); const onOpen = createEmitter('open');
const onClose = createEmitter('close'); const onClose = createEmitter('close');
const onOpened = createEmitter('opened'); const onOpened = createEmitter('opened');
@ -53,14 +75,17 @@ export default createComponent({
emit('closed'); emit('closed');
}; };
const onClickWrapper = (event) => { const onClickWrapper = (event: MouseEvent) => {
// prevent being identified as clicking outside and closed when using teleport // prevent being identified as clicking outside and closed when using teleport
if (props.teleport) { if (props.teleport) {
event.stopPropagation(); event.stopPropagation();
} }
}; };
const toggle = (show = !state.showPopup, options = {}) => { const toggle = (
show = !state.showPopup,
options: { immediate?: boolean } = {}
) => {
if (show === state.showPopup) { if (show === state.showPopup) {
return; return;
} }
@ -89,7 +114,7 @@ export default createComponent({
return match.length ? match[0].text : ''; return match.length ? match[0].text : '';
}; };
const renderOption = (option) => { const renderOption = (option: DropdownItemOption) => {
const { activeColor } = parent.props; const { activeColor } = parent.props;
const active = option.value === props.modelValue; const active = option.value === props.modelValue;
@ -129,7 +154,10 @@ export default createComponent({
closeOnClickOverlay, closeOnClickOverlay,
} = parent.props; } = parent.props;
const style = { zIndex }; const style: CSSProperties = {
zIndex: zIndex !== undefined ? +zIndex : undefined,
};
if (direction === 'down') { if (direction === 'down') {
style.top = `${offset.value}px`; style.top = `${offset.value}px`;
} else { } else {

View File

@ -1,7 +1,7 @@
import { ref, computed } from 'vue'; import { ref, computed, PropType, CSSProperties, Ref } from 'vue';
// Utils // Utils
import { createNamespace, isDef } from '../utils'; import { isDef, ComponentInstance, createNamespace } from '../utils';
// Composition // Composition
import { import {
@ -16,6 +16,20 @@ const [createComponent, bem] = createNamespace('dropdown-menu');
export const DROPDOWN_KEY = 'vanDropdownMenu'; export const DROPDOWN_KEY = 'vanDropdownMenu';
export type DropdownMenuDirection = 'up' | 'down';
export type DropdownMenuProvide = {
props: {
zIndex?: number | string;
overlay: boolean;
duration: number | string;
direction: DropdownMenuDirection;
activeColor?: string;
closeOnClickOverlay: boolean;
};
offset: Ref<number>;
};
export default createComponent({ export default createComponent({
props: { props: {
zIndex: [Number, String], zIndex: [Number, String],
@ -29,7 +43,7 @@ export default createComponent({
default: 0.2, default: 0.2,
}, },
direction: { direction: {
type: String, type: String as PropType<DropdownMenuDirection>,
default: 'down', default: 'down',
}, },
closeOnClickOutside: { closeOnClickOutside: {
@ -43,11 +57,13 @@ export default createComponent({
}, },
setup(props, { slots }) { setup(props, { slots }) {
const root = ref(); const root = ref<HTMLElement>();
const barRef = ref<HTMLElement>();
const offset = ref(0); const offset = ref(0);
const barRef = ref();
const { children, linkChildren } = useChildren(DROPDOWN_KEY); const { children, linkChildren } = useChildren<ComponentInstance>(
DROPDOWN_KEY
);
const scrollParent = useScrollParent(root); const scrollParent = useScrollParent(root);
const opened = computed(() => const opened = computed(() =>
@ -57,8 +73,8 @@ export default createComponent({
const barStyle = computed(() => { const barStyle = computed(() => {
if (opened.value && isDef(props.zIndex)) { if (opened.value && isDef(props.zIndex)) {
return { return {
zIndex: 1 + props.zIndex, zIndex: +props.zIndex + 1,
}; } as CSSProperties;
} }
}); });
@ -87,7 +103,7 @@ export default createComponent({
} }
}; };
const toggleItem = (active) => { const toggleItem = (active: number) => {
children.forEach((item, index) => { children.forEach((item, index) => {
if (index === active) { if (index === active) {
updateOffset(); updateOffset();
@ -98,7 +114,7 @@ export default createComponent({
}); });
}; };
const renderTitle = (item, index) => { const renderTitle = (item: ComponentInstance, index: number) => {
const { showPopup } = item.state; const { showPopup } = item.state;
const { disabled, titleClass } = item; const { disabled, titleClass } = item;

View File

@ -10,12 +10,15 @@ declare module 'vue' {
// see: https://github.com/vuejs/vue-next/issues/1553 // see: https://github.com/vuejs/vue-next/issues/1553
// https://github.com/vuejs/vue-next/issues/3029 // https://github.com/vuejs/vue-next/issues/3029
onBlur?: EventHandler; onBlur?: EventHandler;
onOpen?: EventHandler;
onEdit?: EventHandler; onEdit?: EventHandler;
onClose?: EventHandler;
onFocus?: EventHandler; onFocus?: EventHandler;
onInput?: EventHandler; onInput?: EventHandler;
onClick?: EventHandler; onClick?: EventHandler;
onPress?: EventHandler; onPress?: EventHandler;
onCancel?: EventHandler; onCancel?: EventHandler;
onOpened?: EventHandler;
onClosed?: EventHandler; onClosed?: EventHandler;
onChange?: EventHandler; onChange?: EventHandler;
onSubmit?: EventHandler; onSubmit?: EventHandler;