diff --git a/packages/overlayscrollbars-react/README.md b/packages/overlayscrollbars-react/README.md
index b87cb00..7815720 100644
--- a/packages/overlayscrollbars-react/README.md
+++ b/packages/overlayscrollbars-react/README.md
@@ -1,46 +1,136 @@
-# Getting Started with Create React App
+
+
+
+
+
+
+
-This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
+# OverlayScrollbars for React
-## Available Scripts
+This is the official OverlayScrollbars React wrapper.
-In the project directory, you can run:
+## Installation
-### `npm start`
+```sh
+npm install overlayscrollbars-react
+```
-Runs the app in the development mode.\
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
+## Peer Dependencies
-The page will reload if you make edits.\
-You will also see any lint errors in the console.
+OverlayScrollbars for React has the following **peer dependencies**:
-### `npm test`
+- The vanilla JavaScript library: [overlayscrollbars](https://www.npmjs.com/package/overlayscrollbars)
-Launches the test runner in the interactive watch mode.\
-See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
+```
+npm install overlayscrollbars
+```
-### `npm run build`
+- The React framework: [react](https://www.npmjs.com/package/react)
-Builds the app for production to the `build` folder.\
-It correctly bundles React in production mode and optimizes the build for the best performance.
+```
+npm install react
+```
-The build is minified and the filenames include the hashes.\
-Your app is ready to be deployed!
+## Usage
-See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
+The first step is to import the CSS file into your app:
+```ts
+import 'overlayscrollbars/overlayscrollbars.css';
+```
-### `npm run eject`
+> __Note__: In older node versions use `'overlayscrollbars/styles/overlayscrollbars.css'` as the import path for the CSS file.
-**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
+## Component
-If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
+The main entry point is the `OverlayScrollbarsComponent` which can be used in your application as a component:
-Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
+```js
+import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
-You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
+// ...
-## Learn More
+
+ example content
+
+```
-You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
+### Properties
-To learn React, check out the [React documentation](https://reactjs.org/).
+The component accepts all properties which intrinsic JSX elements such as `div` and `span` accept.
+Additionally it has three optional properties: `element`, `options` and `events`.
+
+- `element`: accepts a `string` which represents the tag of the root element.
+- `options`: accepts an `object` which represents the OverlayScrollbars options.
+- `events`: accepts an `object` which represents the OverlayScrollbars events.
+
+None of these properties has to be memoized.
+
+```jsx
+// example usage
+ { /* ... */ } }}
+/>
+```
+
+### Ref
+
+The `ref` of the `OverlayScrollbarsComponent` will give you an object with which you can access the OverlayScrollbars `instance` and the root `element` of the component.
+The ref object has two properties:
+
+- `instance`: a function which returns the OverlayScrollbars instance.
+- `element`: a function which returns the root element.
+
+## Hook
+
+In case the `OverlayScrollbarsComponent` is not enough, you can also use the `useOverlayScrollbars` hook:
+
+```js
+import { useOverlayScrollbars } from "overlayscrollbars-react";
+
+// example
+const Component = () => {
+ const ref = useRef();
+ const [initialize, instance] = useOverlayScrollbars({ options, events });
+
+ useEffect(() => {
+ const osInstance = initialize(ref.current);
+ return () => osInstance.destroy();
+ }, [initialize]);
+
+ return
+}
+```
+
+The hook is for advanced usage and lets you control the whole initialization process. This is useful if you want to integrate it with other plugins such as `react-window` or `react-virtualized`.
+
+### Parameters
+
+Parameters are optional and similar to the `OverlayScrollbarsComponent`.
+Its an `object` with two optional properties:
+
+- `options`: accepts an `object` which represents the OverlayScrollbars options.
+- `events`: accepts an `object` which represents the OverlayScrollbars events.
+
+
+### Return
+
+The `useOverlayScrollbars` hook returns a `tuple` with two values:
+
+- 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.
+
+The identity of both functions is stable and won't change, thus they can safely be used in any dependency array.
+
+## License
+
+MIT
diff --git a/packages/overlayscrollbars-react/package.json b/packages/overlayscrollbars-react/package.json
index 163ec80..c210e86 100644
--- a/packages/overlayscrollbars-react/package.json
+++ b/packages/overlayscrollbars-react/package.json
@@ -26,7 +26,7 @@
"module": "./dist/overlayscrollbars-react.es.js",
"types": "./dist/overlayscrollbars-react.d.ts",
"peerDependencies": {
- "react": ">=16.4.0",
+ "react": ">=16.8.0",
"overlayscrollbars": "^2.0.0"
},
"devDependencies": {
diff --git a/packages/overlayscrollbars-react/src/OverlayScrollbarsComponent.tsx b/packages/overlayscrollbars-react/src/OverlayScrollbarsComponent.tsx
index 9a58529..04cb6d1 100644
--- a/packages/overlayscrollbars-react/src/OverlayScrollbarsComponent.tsx
+++ b/packages/overlayscrollbars-react/src/OverlayScrollbarsComponent.tsx
@@ -17,8 +17,8 @@ export type OverlayScrollbarsComponentProps {
/** Returns the OverlayScrollbars instance or null if not initialized. */
instance(): OverlayScrollbars | null;
- /** Returns the target element. */
- target(): ElementRef | null;
+ /** Returns the root element. */
+ element(): ElementRef | null;
}
const OverlayScrollbarsComponent = (
@@ -28,13 +28,13 @@ const OverlayScrollbarsComponent = (
const { element = 'div', options, events, children, ...other } = props;
const Tag = element;
- const [initialize, instance] = useOverlayScrollbars(options, events);
- const osTargetRef = useRef>(null);
- const osChildrenRef = useRef(null);
+ const [initialize, instance] = useOverlayScrollbars({ options, events });
+ const elementRef = useRef>(null);
+ const childrenRef = useRef(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 = (
return () => osInstance.destroy();
}
- }, []);
+ }, [initialize]);
useImperativeHandle(
ref,
() => {
return {
instance,
- target: () => osTargetRef.current,
+ element: () => elementRef.current,
};
},
[]
@@ -61,8 +61,8 @@ const OverlayScrollbarsComponent = (
return (
// @ts-ignore
-
- {children}
+
+ {children}
);
};
diff --git a/packages/overlayscrollbars-react/src/useOverlayScrollbars.ts b/packages/overlayscrollbars-react/src/useOverlayScrollbars.ts
index 60c21ba..f2a381a 100644
--- a/packages/overlayscrollbars-react/src/useOverlayScrollbars.ts
+++ b/packages/overlayscrollbars-react/src/useOverlayScrollbars.ts
@@ -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(null);
const offInitialEventsRef = useRef<(() => void) | void>();
const optionsRef = useRef();
@@ -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,
+ ],
+ []
+ );
};
diff --git a/packages/overlayscrollbars-react/test/OverlayScrollbarsComponent.test.tsx b/packages/overlayscrollbars-react/test/OverlayScrollbarsComponent.test.tsx
index 00aed6a..f43fee9 100644
--- a/packages/overlayscrollbars-react/test/OverlayScrollbarsComponent.test.tsx
+++ b/packages/overlayscrollbars-react/test/OverlayScrollbarsComponent.test.tsx
@@ -97,11 +97,11 @@ describe('OverlayScrollbarsComponent', () => {
const ref: RefObject = { current: null };
const { container } = render();
- const { instance, target } = ref.current!;
+ const { instance, element } = ref.current!;
expect(instance).toBeTypeOf('function');
- expect(target).toBeTypeOf('function');
+ expect(element).toBeTypeOf('function');
expect(OverlayScrollbars.valid(instance())).toBe(true);
- expect(target()).toBe(container.firstElementChild);
+ expect(element()).toBe(container.firstElementChild);
});
test('options', () => {