add emits to vue

This commit is contained in:
Rene Haas
2022-11-05 00:19:42 +01:00
parent 29a77728fc
commit c07071ed91
3 changed files with 61 additions and 17 deletions
@@ -1,11 +1,14 @@
<script lang="ts">
import { defineComponent, watchPostEffect, onBeforeUnmount, shallowRef, toRef } from 'vue';
import { defineComponent, watch, watchPostEffect, ref, shallowRef, toRefs, onUnmounted } from 'vue';
import { useOverlayScrollbars } from './useOverlayScrollbars';
import type {
OverlayScrollbarsComponentProps,
OverlayScrollbarsComponentRef,
} from './OverlayScrollbarsComponent.types';
import type { PropType } from 'vue';
import type { EventListeners, EventListenerMap } from 'overlayscrollbars';
const emitNames: (keyof EventListenerMap)[] = ['initialized', 'updated', 'destroyed', 'scroll'];
export default defineComponent({
name: 'OverlayScrollbars',
@@ -17,11 +20,18 @@ export default defineComponent({
options: { type: Object as PropType<OverlayScrollbarsComponentProps['options']> },
events: { type: Object as PropType<OverlayScrollbarsComponentProps['events']> },
},
setup(props, { expose }) {
emits: {
initialized: (...args: EventListenerMap['initialized']) => true,
updated: (...args: EventListenerMap['updated']) => true,
destroyed: (...args: EventListenerMap['destroyed']) => true,
scroll: (...args: EventListenerMap['scroll']) => true,
},
setup(props, { expose, emit }) {
const elementRef = shallowRef<HTMLElement | null>(null);
const slotRef = shallowRef<HTMLElement | null>(null);
const [initialize, instance] = useOverlayScrollbars(props);
const combinedEvents = ref<EventListeners>();
const { element, options, events } = toRefs(props);
const [initialize, instance] = useOverlayScrollbars({ options, events: combinedEvents });
const exposed: OverlayScrollbarsComponentRef = {
instance,
element: () => elementRef.value,
@@ -29,6 +39,26 @@ export default defineComponent({
expose(exposed);
watch(
() => events.value,
(rawCurrEvents) => {
const currEvents = rawCurrEvents || {};
combinedEvents.value = emitNames.reduce<EventListeners>(
<N extends keyof EventListeners>(obj: EventListeners, name: N) => {
const eventListener = currEvents[name];
obj[name] = [
// @ts-ignore
(...args: EventListenerMap[N]) => emit(name, ...args),
...(Array.isArray(eventListener) ? eventListener : [eventListener]).filter(Boolean),
];
return obj;
},
{}
);
},
{ deep: true, immediate: true }
);
watchPostEffect((onCleanup) => {
const { value: elm } = elementRef;
const { value: slotElm } = slotRef;
@@ -45,9 +75,9 @@ export default defineComponent({
}
});
onBeforeUnmount(() => instance()?.destroy());
onUnmounted(() => instance()?.destroy());
return { elementRef, slotRef, element: toRef(props, 'element') };
return { elementRef, slotRef, element };
},
});
</script>
@@ -46,14 +46,10 @@ export const useOverlayScrollbars = (
watch(
() => unref(paramsRef.value.options),
() => {
const {
value: { options: rawOptions },
} = paramsRef;
(options) => {
const {
value: { instance },
} = variables;
const options = unref(rawOptions);
variables.value.options = options;
@@ -66,14 +62,10 @@ export const useOverlayScrollbars = (
watch(
() => unref(paramsRef.value.events),
() => {
const {
value: { events: rawEvents },
} = paramsRef;
(events) => {
const {
value: { instance },
} = variables;
const events = unref(rawEvents);
variables.value.events = events;
@@ -1,7 +1,7 @@
import { onMounted, ref, toRefs } from 'vue';
import { describe, test, expect, vitest } from 'vitest';
import { OverlayScrollbars } from 'overlayscrollbars';
import { render, screen } from '@testing-library/vue';
import { fireEvent, render, screen } from '@testing-library/vue';
import userEvent from '@testing-library/user-event';
import { OverlayScrollbarsComponent } from '~/overlayscrollbars-vue';
@@ -254,4 +254,26 @@ describe('OverlayScrollbarsComponent', () => {
expect(onUpdatedInitial).toHaveBeenCalledTimes(3);
expect(onUpdated).toHaveBeenCalledTimes(3);
});
test('emits', async () => {
const { emitted, unmount, container } = render(OverlayScrollbarsComponent);
expect(emitted('initialized')).toEqual([[expect.any(Object)]]);
expect(emitted('updated')).toEqual([[expect.any(Object), expect.any(Object)]]);
expect(emitted('scroll')).toBeUndefined();
expect(emitted('destroyed')).toBeUndefined();
container.querySelectorAll('*').forEach((e) => {
fireEvent.scroll(e);
});
await Promise.resolve();
expect(emitted('scroll')).toEqual([[expect.any(Object), expect.any(UIEvent)]]);
expect(emitted('destroyed')).toBeUndefined();
unmount();
expect(emitted('destroyed')).toEqual([[expect.any(Object), false]]);
});
});