mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-18 18:01:04 +03:00
101 lines
3.0 KiB
Svelte
101 lines
3.0 KiB
Svelte
<script lang="ts">
|
|
import { onMount, afterUpdate, createEventDispatcher } from 'svelte';
|
|
import { OverlayScrollbars } from 'overlayscrollbars';
|
|
import type { EventListeners, EventListenerArgs } from 'overlayscrollbars';
|
|
import type { OverlayScrollbarsComponentProps$, OverlayScrollbarsComponentRef$ } from './OverlayScrollbarsComponent.types';
|
|
|
|
type EmitEventsMap = {
|
|
[N in keyof EventListenerArgs]: `os${Capitalize<N>}`;
|
|
};
|
|
|
|
export let element: OverlayScrollbarsComponentProps$["element"] = 'div';
|
|
export let options: OverlayScrollbarsComponentProps$["options"] = undefined;
|
|
export let events: OverlayScrollbarsComponentProps$["events"] = undefined;
|
|
|
|
let instance: OverlayScrollbars | null = null;
|
|
let elementRef: HTMLElement | null = null;
|
|
let slotRef: HTMLElement | null = null;
|
|
let combinedEvents: OverlayScrollbarsComponentProps$["events"] = undefined;
|
|
let prevElement: string | undefined;
|
|
|
|
const initialize = () => {
|
|
instance?.destroy();
|
|
instance = OverlayScrollbars(
|
|
{
|
|
target: elementRef!,
|
|
elements: {
|
|
viewport: slotRef,
|
|
content: slotRef
|
|
}
|
|
},
|
|
options || {},
|
|
combinedEvents || {}
|
|
);
|
|
prevElement = element;
|
|
return () => instance?.destroy();
|
|
};
|
|
const dispatchEvents: EmitEventsMap = {
|
|
initialized: 'osInitialized',
|
|
updated: 'osUpdated',
|
|
destroyed: 'osDestroyed',
|
|
scroll: 'osScroll',
|
|
};
|
|
const dispatchEvent = createEventDispatcher<{
|
|
osInitialized: EventListenerArgs["initialized"];
|
|
osUpdated: EventListenerArgs["updated"];
|
|
osDestroyed: EventListenerArgs["destroyed"];
|
|
osScroll: EventListenerArgs["scroll"];
|
|
}>();
|
|
|
|
export const osInstance: OverlayScrollbarsComponentRef$["osInstance"] = () => instance;
|
|
export const getElement: OverlayScrollbarsComponentRef$["getElement"] = () => elementRef;
|
|
|
|
onMount(initialize);
|
|
|
|
afterUpdate(() => {
|
|
if (prevElement !== element) {
|
|
initialize();
|
|
}
|
|
});
|
|
|
|
$: {
|
|
const currEvents = events || {};
|
|
combinedEvents = (
|
|
Object.keys(dispatchEvents) as (keyof EventListeners)[]
|
|
).reduce<EventListeners>(<N extends keyof EventListeners>(obj: EventListeners, name: N) => {
|
|
const eventListener = currEvents[name];
|
|
obj[name] = [
|
|
(...args: EventListenerArgs[N]) =>
|
|
dispatchEvent(
|
|
dispatchEvents[name],
|
|
// @ts-ignore
|
|
args
|
|
),
|
|
...(Array.isArray(eventListener) ? eventListener : [eventListener]).filter(Boolean),
|
|
];
|
|
return obj;
|
|
}, {});
|
|
}
|
|
|
|
$: {
|
|
if (OverlayScrollbars.valid(instance)) {
|
|
instance.options(options || {}, true);
|
|
}
|
|
}
|
|
|
|
$: {
|
|
if (OverlayScrollbars.valid(instance)) {
|
|
instance.on(
|
|
/* c8 ignore next */
|
|
combinedEvents || {},
|
|
true
|
|
);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<svelte:element data-overlayscrollbars-initialize="" this={element} bind:this={elementRef} {...$$restProps}>
|
|
<div bind:this={slotRef}>
|
|
<slot></slot>
|
|
</div>
|
|
</svelte:element> |