mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-05-26 23:14:07 +03:00
improve framework wrapper tests and vue component
This commit is contained in:
@@ -240,4 +240,18 @@ describe('OverlayScrollbarsComponent', () => {
|
||||
expect(onUpdatedInitial).toHaveBeenCalledTimes(3);
|
||||
expect(onUpdated).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
test('destroy', () => {
|
||||
const ref: RefObject<OverlayScrollbarsComponentRef> = { current: null };
|
||||
const { unmount } = render(<OverlayScrollbarsComponent ref={ref} />);
|
||||
|
||||
const { instance } = ref.current!;
|
||||
|
||||
expect(OverlayScrollbars.valid(instance())).toBe(true);
|
||||
|
||||
unmount();
|
||||
|
||||
expect(instance()).toBeDefined();
|
||||
expect(OverlayScrollbars.valid(instance())).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1247.05px" height="1079.989px" viewBox="336.436 0.005 1247.05 1079.989" enable-background="new 336.436 0.005 1247.05 1079.989" xml:space="preserve">
|
||||
<g transform="matrix(1.3333 0 0 -1.3333 -76.311 313.34)">
|
||||
<g transform="translate(178.06 235.01)">
|
||||
<path fill="#41B883" d="M707.163-0.003l-108-187.062l-108,187.062H131.508l467.655-810.012L1066.819-0.003H707.163z"/>
|
||||
</g>
|
||||
<g transform="translate(178.06 235.01)">
|
||||
<path fill="#34495E" d="M707.163-0.003l-108-187.062l-108,187.062H318.57l280.593-485.998L879.757-0.003H707.163z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69" xmlns:v="https://vecta.io/nano"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
||||
|
Before Width: | Height: | Size: 914 B After Width: | Height: | Size: 308 B |
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, watch, watchPostEffect, ref, shallowRef, toRefs, onUnmounted } from 'vue';
|
||||
<script setup lang="ts">
|
||||
import { ref, unref, shallowRef, toRefs, watch, watchPostEffect, onUnmounted } from 'vue';
|
||||
import { useOverlayScrollbars } from './useOverlayScrollbars';
|
||||
import type {
|
||||
OverlayScrollbarsComponentProps,
|
||||
@@ -9,77 +9,70 @@ import type { PropType } from 'vue';
|
||||
import type { EventListeners, EventListenerMap } from 'overlayscrollbars';
|
||||
|
||||
const emitNames: (keyof EventListenerMap)[] = ['initialized', 'updated', 'destroyed', 'scroll'];
|
||||
|
||||
export default defineComponent({
|
||||
name: 'OverlayScrollbars',
|
||||
props: {
|
||||
element: {
|
||||
type: String as PropType<OverlayScrollbarsComponentProps['element']>,
|
||||
default: 'div',
|
||||
},
|
||||
options: { type: Object as PropType<OverlayScrollbarsComponentProps['options']> },
|
||||
events: { type: Object as PropType<OverlayScrollbarsComponentProps['events']> },
|
||||
},
|
||||
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 combinedEvents = ref<EventListeners>();
|
||||
const { element, options, events } = toRefs(props);
|
||||
const [initialize, instance] = useOverlayScrollbars({ options, events: combinedEvents });
|
||||
const exposed: OverlayScrollbarsComponentRef = {
|
||||
instance,
|
||||
element: () => elementRef.value,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
if (elm && slotElm) {
|
||||
const osInstance = initialize({
|
||||
target: elm,
|
||||
elements: {
|
||||
viewport: slotElm,
|
||||
content: slotElm,
|
||||
},
|
||||
});
|
||||
onCleanup(() => osInstance.destroy());
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => instance()?.destroy());
|
||||
|
||||
return { elementRef, slotRef, element };
|
||||
const props = defineProps({
|
||||
element: {
|
||||
type: String as PropType<OverlayScrollbarsComponentProps['element']>,
|
||||
default: 'div',
|
||||
},
|
||||
options: { type: Object as PropType<OverlayScrollbarsComponentProps['options']> },
|
||||
events: { type: Object as PropType<OverlayScrollbarsComponentProps['events']> },
|
||||
});
|
||||
const emits = defineEmits({
|
||||
initialized: (...args: EventListenerMap['initialized']) => true,
|
||||
updated: (...args: EventListenerMap['updated']) => true,
|
||||
destroyed: (...args: EventListenerMap['destroyed']) => true,
|
||||
scroll: (...args: EventListenerMap['scroll']) => true,
|
||||
} as Record<keyof EventListenerMap, any>);
|
||||
|
||||
const elementRef = shallowRef<HTMLElement | null>(null);
|
||||
const slotRef = shallowRef<HTMLElement | null>(null);
|
||||
const combinedEvents = ref<EventListeners>();
|
||||
const { element, options, events } = toRefs(props);
|
||||
const [initialize, instance] = useOverlayScrollbars({ options, events: combinedEvents });
|
||||
const exposed: OverlayScrollbarsComponentRef = {
|
||||
instance,
|
||||
element: () => elementRef.value,
|
||||
};
|
||||
|
||||
defineExpose(exposed);
|
||||
|
||||
onUnmounted(() => instance()?.destroy());
|
||||
|
||||
watchPostEffect((onCleanup) => {
|
||||
const { value: elm } = elementRef;
|
||||
const { value: slotElm } = slotRef;
|
||||
|
||||
if (elm && slotElm) {
|
||||
const osInstance = initialize({
|
||||
target: elm,
|
||||
elements: {
|
||||
viewport: slotElm,
|
||||
content: slotElm,
|
||||
},
|
||||
});
|
||||
onCleanup(() => osInstance.destroy());
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => unref(events),
|
||||
(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]) => emits(name, ...args),
|
||||
...(Array.isArray(eventListener) ? eventListener : [eventListener]).filter(Boolean),
|
||||
];
|
||||
return obj;
|
||||
},
|
||||
{}
|
||||
);
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -70,7 +70,11 @@ export const useOverlayScrollbars = (
|
||||
variables.value.events = events;
|
||||
|
||||
if (OverlayScrollbars.valid(instance)) {
|
||||
instance.on(events || {}, true);
|
||||
instance.on(
|
||||
/* c8 ignore next */
|
||||
events || {},
|
||||
true
|
||||
);
|
||||
}
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
|
||||
@@ -255,6 +255,30 @@ describe('OverlayScrollbarsComponent', () => {
|
||||
expect(onUpdated).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
test('destroy', () => {
|
||||
const osRef = ref();
|
||||
const { unmount } = render({
|
||||
setup() {
|
||||
const componentRef = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
osRef.value = componentRef.value;
|
||||
});
|
||||
|
||||
return () => <OverlayScrollbarsComponent ref={componentRef} />;
|
||||
},
|
||||
});
|
||||
|
||||
const { instance } = osRef.value!;
|
||||
|
||||
expect(OverlayScrollbars.valid(instance())).toBe(true);
|
||||
|
||||
unmount();
|
||||
|
||||
expect(instance()).toBeDefined();
|
||||
expect(OverlayScrollbars.valid(instance())).toBe(false);
|
||||
});
|
||||
|
||||
test('emits', async () => {
|
||||
const { emitted, unmount, container } = render(OverlayScrollbarsComponent);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user