mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-10 22:22:27 +03:00
99 lines
2.9 KiB
TypeScript
99 lines
2.9 KiB
TypeScript
import {
|
|
mergeProps,
|
|
splitProps,
|
|
children,
|
|
onCleanup,
|
|
createEffect,
|
|
createRenderEffect,
|
|
createSignal,
|
|
} from 'solid-js';
|
|
import { Dynamic } from 'solid-js/web';
|
|
import type { JSX, ParentProps, ComponentProps, Ref } from 'solid-js';
|
|
import type { OverlayScrollbars, PartialOptions, EventListeners } from 'overlayscrollbars';
|
|
import { createOverlayScrollbars } from './createOverlayScrollbars';
|
|
|
|
type InferGeneric<T> = T extends JSX.HTMLAttributes<infer G> ? G : never;
|
|
|
|
export type OverlayScrollbarsComponentProps<T extends keyof JSX.IntrinsicElements = 'div'> = Omit<
|
|
ComponentProps<T>,
|
|
'ref'
|
|
> &
|
|
ParentProps<{
|
|
/** Tag of the root element. */
|
|
element?: T;
|
|
/** OverlayScrollbars options. */
|
|
options?: PartialOptions | false | null;
|
|
/** OverlayScrollbars events. */
|
|
events?: EventListeners | false | null;
|
|
/** Whether to defer the initialization to a point in time when the browser is idle. (or to the next frame if `window.requestIdleCallback` is not supported) */
|
|
defer?: boolean | IdleRequestOptions;
|
|
/** OverlayScrollbarsComponent ref. */
|
|
ref?: Exclude<Ref<OverlayScrollbarsComponentRef>, OverlayScrollbarsComponentRef>;
|
|
}>;
|
|
|
|
export interface OverlayScrollbarsComponentRef<T extends keyof JSX.IntrinsicElements = 'div'> {
|
|
/** Returns the OverlayScrollbars instance or null if not initialized. */
|
|
osInstance(): OverlayScrollbars | null;
|
|
/** Returns the root element. */
|
|
getElement(): InferGeneric<JSX.IntrinsicElements[T]> | null;
|
|
}
|
|
|
|
export const OverlayScrollbarsComponent = <T extends keyof JSX.IntrinsicElements = 'div'>(
|
|
props: OverlayScrollbarsComponentProps<T>
|
|
) => {
|
|
const [finalProps, other] = splitProps(
|
|
mergeProps({ element: 'div' }, props as OverlayScrollbarsComponentProps),
|
|
['element', 'options', 'events', 'defer', 'ref', 'children']
|
|
);
|
|
const [elementRef, setElementRef] = createSignal<HTMLDivElement | undefined>();
|
|
const [childrenRef, setChildrenRef] = createSignal<HTMLDivElement | undefined>();
|
|
const [initialize, instance] = createOverlayScrollbars(finalProps);
|
|
|
|
createEffect(() => {
|
|
const currElement = elementRef();
|
|
const currChildrenElement = childrenRef();
|
|
|
|
if (currElement && currChildrenElement) {
|
|
initialize({
|
|
target: currElement,
|
|
elements: {
|
|
viewport: currChildrenElement,
|
|
content: currChildrenElement,
|
|
},
|
|
});
|
|
|
|
onCleanup(() => {
|
|
instance()?.destroy();
|
|
});
|
|
}
|
|
});
|
|
|
|
createRenderEffect(() => {
|
|
finalProps.ref?.({
|
|
osInstance: instance,
|
|
getElement: () =>
|
|
/* c8 ignore next */
|
|
elementRef() || null,
|
|
});
|
|
});
|
|
|
|
return (
|
|
<Dynamic
|
|
component={finalProps.element}
|
|
data-overlayscrollbars-initialize=""
|
|
ref={(ref: any) => {
|
|
setElementRef(ref);
|
|
}}
|
|
{...other}
|
|
>
|
|
<div
|
|
ref={(ref: any) => {
|
|
setChildrenRef(ref);
|
|
}}
|
|
>
|
|
{children(() => finalProps.children)}
|
|
</div>
|
|
</Dynamic>
|
|
);
|
|
};
|