finish overlayscrollbars-react

This commit is contained in:
Rene Haas
2022-11-02 18:28:57 +01:00
parent cf9cda1cf6
commit 23f120e164
5 changed files with 166 additions and 67 deletions
@@ -17,8 +17,8 @@ export type OverlayScrollbarsComponentProps<T extends keyof JSX.IntrinsicElement
export interface OverlayScrollbarsComponentRef<T extends keyof JSX.IntrinsicElements = 'div'> {
/** Returns the OverlayScrollbars instance or null if not initialized. */
instance(): OverlayScrollbars | null;
/** Returns the target element. */
target(): ElementRef<T> | null;
/** Returns the root element. */
element(): ElementRef<T> | null;
}
const OverlayScrollbarsComponent = <T extends keyof JSX.IntrinsicElements>(
@@ -28,13 +28,13 @@ const OverlayScrollbarsComponent = <T extends keyof JSX.IntrinsicElements>(
const { element = 'div', options, events, children, ...other } = props;
const Tag = element;
const [initialize, instance] = useOverlayScrollbars(options, events);
const osTargetRef = useRef<ElementRef<T>>(null);
const osChildrenRef = useRef<HTMLDivElement>(null);
const [initialize, instance] = useOverlayScrollbars({ options, events });
const elementRef = useRef<ElementRef<T>>(null);
const childrenRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const { current: targetElm } = osTargetRef;
const { current: childrenElm } = osChildrenRef;
const { current: targetElm } = elementRef;
const { current: childrenElm } = childrenRef;
if (targetElm && childrenElm) {
const osInstance = initialize({
target: targetElm as any,
@@ -46,14 +46,14 @@ const OverlayScrollbarsComponent = <T extends keyof JSX.IntrinsicElements>(
return () => osInstance.destroy();
}
}, []);
}, [initialize]);
useImperativeHandle(
ref,
() => {
return {
instance,
target: () => osTargetRef.current,
element: () => elementRef.current,
};
},
[]
@@ -61,8 +61,8 @@ const OverlayScrollbarsComponent = <T extends keyof JSX.IntrinsicElements>(
return (
// @ts-ignore
<Tag data-overlayscrollbars="" {...other} ref={osTargetRef}>
<div ref={osChildrenRef}>{children}</div>
<Tag data-overlayscrollbars="" {...other} ref={elementRef}>
<div ref={childrenRef}>{children}</div>
</Tag>
);
};
@@ -1,7 +1,14 @@
import { useEffect, useCallback, useRef } from 'react';
import { useEffect, useMemo, useRef } from 'react';
import { OverlayScrollbars } from 'overlayscrollbars';
import type { PartialOptions, InitializationTarget, EventListeners } from 'overlayscrollbars';
export interface UseOverlayScrollbarsParams {
/** OverlayScrollbars options. */
options?: PartialOptions;
/** OverlayScrollbars events. */
events?: EventListeners;
}
export type UseOverlayScrollbarsInitialization = (
target: InitializationTarget
) => OverlayScrollbars;
@@ -10,16 +17,15 @@ export type UseOverlayScrollbarsInstance = () => OverlayScrollbars | null;
/**
* Hook for advanced usage of OverlayScrollbars. (When the OverlayScrollbarsComponent is not enough)
* @param options OverlayScrollbars options.
* @param events OverlayScrollbars events.
* @param params Parameters for customization.
* @returns A tuple with two values:
* The first value is the initialization function.
* The second value is a function which returns the current OverlayScrollbars instance or null if not initialized.
* The first value is the initialization function, it takes one argument which is the `InitializationTarget` and returns the OverlayScrollbars instance.
* The second value is a function which returns the current OverlayScrollbars instance or `null` if not initialized.
*/
export const useOverlayScrollbars = (
options?: PartialOptions,
events?: EventListeners
params?: UseOverlayScrollbarsParams
): [UseOverlayScrollbarsInitialization, UseOverlayScrollbarsInstance] => {
const { options, events } = params || {};
const osInstanceRef = useRef<OverlayScrollbars | null>(null);
const offInitialEventsRef = useRef<(() => void) | void>();
const optionsRef = useRef<PartialOptions>();
@@ -44,26 +50,29 @@ export const useOverlayScrollbars = (
optionsRef.current = options;
eventsRef.current = events;
return [
useCallback((target: InitializationTarget): OverlayScrollbars => {
// if already initialized return the current instance
const presentInstance = osInstanceRef.current;
if (OverlayScrollbars.valid(presentInstance)) {
return presentInstance;
}
return useMemo<[UseOverlayScrollbarsInitialization, UseOverlayScrollbarsInstance]>(
() => [
(target: InitializationTarget): OverlayScrollbars => {
// if already initialized return the current instance
const presentInstance = osInstanceRef.current;
if (OverlayScrollbars.valid(presentInstance)) {
return presentInstance;
}
const currOptions = optionsRef.current || {};
const currEvents = eventsRef.current || {};
const osInstance = (osInstanceRef.current = OverlayScrollbars(
target,
currOptions,
currEvents
));
const currOptions = optionsRef.current || {};
const currEvents = eventsRef.current || {};
const osInstance = (osInstanceRef.current = OverlayScrollbars(
target,
currOptions,
currEvents
));
offInitialEventsRef.current = osInstance.on(currEvents);
offInitialEventsRef.current = osInstance.on(currEvents);
return osInstance;
}, []),
useCallback(() => osInstanceRef.current, []),
];
return osInstance;
},
() => osInstanceRef.current,
],
[]
);
};