mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-23 15:20:37 +03:00
overlayscrollbars-vue v0.5.0
This commit is contained in:
Generated
+1
-1
@@ -24,7 +24,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/overlayscrollbars-react/dist": {
|
"../../packages/overlayscrollbars-react/dist": {
|
||||||
"name": "overlayscrollbars-react",
|
"name": "overlayscrollbars-react",
|
||||||
"version": "0.4.0",
|
"version": "0.5.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"overlayscrollbars": "^2.0.0",
|
"overlayscrollbars": "^2.0.0",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ function App() {
|
|||||||
<OverlayScrollbarsComponent
|
<OverlayScrollbarsComponent
|
||||||
style={{ width: '222px', height: '222px' }}
|
style={{ width: '222px', height: '222px' }}
|
||||||
options={{ scrollbars: { theme: 'os-theme-light' } }}
|
options={{ scrollbars: { theme: 'os-theme-light' } }}
|
||||||
|
defer
|
||||||
>
|
>
|
||||||
<img src={logo} className="App-logo" alt="React logo" width="333" height="333" />
|
<img src={logo} className="App-logo" alt="React logo" width="333" height="333" />
|
||||||
</OverlayScrollbarsComponent>
|
</OverlayScrollbarsComponent>
|
||||||
|
|||||||
Generated
+1
-1
@@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/overlayscrollbars-vue/dist": {
|
"../../packages/overlayscrollbars-vue/dist": {
|
||||||
"name": "overlayscrollbars-vue",
|
"name": "overlayscrollbars-vue",
|
||||||
"version": "0.4.0",
|
"version": "0.5.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"overlayscrollbars": "^2.0.0",
|
"overlayscrollbars": "^2.0.0",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const options: PartialOptions = {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<OverlayScrollbarsComponent style="height: 222px; width: 222px" :options="options">
|
<OverlayScrollbarsComponent style="height: 222px; width: 222px" :options="options" defer>
|
||||||
<img alt="Vue logo" class="logo" src="./assets/logo.svg" width="333" height="333" />
|
<img alt="Vue logo" class="logo" src="./assets/logo.svg" width="333" height="333" />
|
||||||
</OverlayScrollbarsComponent>
|
</OverlayScrollbarsComponent>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.5.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
Added the possibility 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)
|
||||||
|
- `OverlayScrollbarsComponent` accepts now the `defer` property
|
||||||
|
- `useOverlayScrollbars` params accept now the `defer` key
|
||||||
|
- `useOverlayScrollbars` will now always try to destroy the instance if the component unmounts.
|
||||||
|
|
||||||
|
### Breaking Changes
|
||||||
|
|
||||||
|
- Because initialization can be deferred now, the `initialize` function of the `useOverlayScrollbars` composable isn't returning the instance anymore. Use the `instance` function of the `useOverlayScrollbars` composable instead.
|
||||||
|
|
||||||
## 0.4.0
|
## 0.4.0
|
||||||
|
|
||||||
Depends on `OverlayScrollbars` version `^2.0.0` and `Vue` version `^3.2.25`.
|
Depends on `OverlayScrollbars` version `^2.0.0` and `Vue` version `^3.2.25`.
|
||||||
|
|||||||
@@ -57,18 +57,21 @@ import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
|
|||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
<OverlayScrollbarsComponent>
|
<OverlayScrollbarsComponent defer>
|
||||||
example content
|
example content
|
||||||
</OverlayScrollbarsComponent>
|
</OverlayScrollbarsComponent>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Properties
|
### Properties
|
||||||
|
|
||||||
It has three optional properties: `element`, `options` and `events`.
|
It has optional properties:
|
||||||
|
|
||||||
- `element`: accepts a `string` which represents the tag of the root element.
|
- `element`: accepts a `string` which represents the tag of the root element.
|
||||||
- `options`: accepts an `object` which represents the OverlayScrollbars options.
|
- `options`: accepts an `object` which represents the OverlayScrollbars options.
|
||||||
- `events`: accepts an `object` which represents the OverlayScrollbars events.
|
- `events`: accepts an `object` which represents the OverlayScrollbars events.
|
||||||
|
- `defer`: accepts an `boolean` or `object`. Defers the initialization to a point in time when the browser is idle.
|
||||||
|
|
||||||
|
> __Note__: Its **highly recommended** to use the `defer` option whenever possible to defer the initialization to a browser's idle period.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
// example usage
|
// example usage
|
||||||
@@ -76,6 +79,7 @@ It has three optional properties: `element`, `options` and `events`.
|
|||||||
element="span"
|
element="span"
|
||||||
options={{ scrollbars: { autoHide: 'scroll' } }}
|
options={{ scrollbars: { autoHide: 'scroll' } }}
|
||||||
events={{ scroll: () => { /* ... */ } }}
|
events={{ scroll: () => { /* ... */ } }}
|
||||||
|
defer
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -116,7 +120,7 @@ import { useOverlayScrollbars } from "overlayscrollbars-vue";
|
|||||||
const Component = {
|
const Component = {
|
||||||
setup() {
|
setup() {
|
||||||
const div = ref(null);
|
const div = ref(null);
|
||||||
const reactiveParams = reactive({ options, events });
|
const reactiveParams = reactive({ options, events, defer });
|
||||||
const [initialize, instance] = useOverlayScrollbars(reactiveParams);
|
const [initialize, instance] = useOverlayScrollbars(reactiveParams);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,6 +136,7 @@ const Component = {
|
|||||||
* const [initialize, instance] = useOverlayScrollbars({
|
* const [initialize, instance] = useOverlayScrollbars({
|
||||||
* options,
|
* options,
|
||||||
* events,
|
* events,
|
||||||
|
* defer,
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -154,12 +159,13 @@ The composable is for advanced usage and lets you control the whole initializati
|
|||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
Parameters are optional and similar to the `OverlayScrollbarsComponent`.
|
Parameters are optional and similar to the `OverlayScrollbarsComponent`.
|
||||||
Its an `object` with two optional properties:
|
Its an `object` with optional properties:
|
||||||
|
|
||||||
- `options`: accepts an `object` which represents the OverlayScrollbars options.
|
- `options`: accepts an `object` which represents the OverlayScrollbars options.
|
||||||
- `events`: accepts an `object` which represents the OverlayScrollbars events.
|
- `events`: accepts an `object` which represents the OverlayScrollbars events.
|
||||||
|
- `defer`: accepts an `boolean` or `object`. Defers the initialization to a point in time when the browser is idle.
|
||||||
|
|
||||||
> __Note__: The object can be a normal, `reactive` or `ref` object. This also applies to the `options` and `events` fields.
|
> __Note__: The object can be a normal, `reactive` or `ref` object. This also applies to all fields.
|
||||||
|
|
||||||
### Return
|
### Return
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "overlayscrollbars-vue",
|
"name": "overlayscrollbars-vue",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.4.0",
|
"version": "0.5.0",
|
||||||
"description": "OverlayScrollbars for Vue.",
|
"description": "OverlayScrollbars for Vue.",
|
||||||
"author": "Rene Haas | KingSora",
|
"author": "Rene Haas | KingSora",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export interface OverlayScrollbarsComponentProps {
|
|||||||
element?: string;
|
element?: string;
|
||||||
options?: PartialOptions | false | null;
|
options?: PartialOptions | false | null;
|
||||||
events?: EventListeners | false | null;
|
events?: EventListeners | false | null;
|
||||||
|
defer?: boolean | IdleRequestOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OverlayScrollbarsComponentRef {
|
export interface OverlayScrollbarsComponentRef {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
options: { type: Object as PropType<OverlayScrollbarsComponentProps['options']> },
|
options: { type: Object as PropType<OverlayScrollbarsComponentProps['options']> },
|
||||||
events: { type: Object as PropType<OverlayScrollbarsComponentProps['events']> },
|
events: { type: Object as PropType<OverlayScrollbarsComponentProps['events']> },
|
||||||
|
defer: { type: [Boolean, Object] as PropType<OverlayScrollbarsComponentProps['defer']> },
|
||||||
});
|
});
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
(name: 'osInitialized', ...args: EventListenerArgs['initialized']): void;
|
(name: 'osInitialized', ...args: EventListenerArgs['initialized']): void;
|
||||||
@@ -36,8 +37,8 @@ const emits = defineEmits<{
|
|||||||
const elementRef = shallowRef<HTMLElement | null>(null);
|
const elementRef = shallowRef<HTMLElement | null>(null);
|
||||||
const slotRef = shallowRef<HTMLElement | null>(null);
|
const slotRef = shallowRef<HTMLElement | null>(null);
|
||||||
const combinedEvents = ref<EventListeners>();
|
const combinedEvents = ref<EventListeners>();
|
||||||
const { element, options, events } = toRefs(props);
|
const { element, options, events, defer } = toRefs(props);
|
||||||
const [initialize, osInstance] = useOverlayScrollbars({ options, events: combinedEvents });
|
const [initialize, osInstance] = useOverlayScrollbars({ options, events: combinedEvents, defer });
|
||||||
const exposed: OverlayScrollbarsComponentRef = {
|
const exposed: OverlayScrollbarsComponentRef = {
|
||||||
osInstance,
|
osInstance,
|
||||||
getElement: () => elementRef.value,
|
getElement: () => elementRef.value,
|
||||||
@@ -45,21 +46,20 @@ const exposed: OverlayScrollbarsComponentRef = {
|
|||||||
|
|
||||||
defineExpose(exposed);
|
defineExpose(exposed);
|
||||||
|
|
||||||
onUnmounted(() => osInstance()?.destroy());
|
|
||||||
|
|
||||||
watchPostEffect((onCleanup) => {
|
watchPostEffect((onCleanup) => {
|
||||||
const { value: elm } = elementRef;
|
const { value: elm } = elementRef;
|
||||||
const { value: slotElm } = slotRef;
|
const { value: slotElm } = slotRef;
|
||||||
|
|
||||||
if (elm && slotElm) {
|
if (elm && slotElm) {
|
||||||
const instance = initialize({
|
initialize({
|
||||||
target: elm,
|
target: elm,
|
||||||
elements: {
|
elements: {
|
||||||
viewport: slotElm,
|
viewport: slotElm,
|
||||||
content: slotElm,
|
content: slotElm,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
onCleanup(() => instance.destroy());
|
|
||||||
|
onCleanup(() => osInstance()?.destroy());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { shallowRef, unref, watch } from 'vue';
|
import { onUnmounted, shallowRef, unref, watch } from 'vue';
|
||||||
import { OverlayScrollbars } from 'overlayscrollbars';
|
import { OverlayScrollbars } from 'overlayscrollbars';
|
||||||
import type { Ref, UnwrapRef } from 'vue';
|
import type { Ref, UnwrapRef } from 'vue';
|
||||||
import type { InitializationTarget } from 'overlayscrollbars';
|
import type { InitializationTarget } from 'overlayscrollbars';
|
||||||
@@ -7,6 +7,11 @@ import type {
|
|||||||
OverlayScrollbarsComponentRef,
|
OverlayScrollbarsComponentRef,
|
||||||
} from './OverlayScrollbarsComponent.types';
|
} from './OverlayScrollbarsComponent.types';
|
||||||
|
|
||||||
|
type Defer = [
|
||||||
|
requestDefer: (callback: () => any, options?: OverlayScrollbarsComponentProps['defer']) => void,
|
||||||
|
cancelDefer: () => void
|
||||||
|
];
|
||||||
|
|
||||||
export interface UseOverlayScrollbarsParams {
|
export interface UseOverlayScrollbarsParams {
|
||||||
/** OverlayScrollbars options. */
|
/** OverlayScrollbars options. */
|
||||||
options?:
|
options?:
|
||||||
@@ -16,16 +21,57 @@ export interface UseOverlayScrollbarsParams {
|
|||||||
events?:
|
events?:
|
||||||
| OverlayScrollbarsComponentProps['events']
|
| OverlayScrollbarsComponentProps['events']
|
||||||
| Ref<OverlayScrollbarsComponentProps['events']>;
|
| Ref<OverlayScrollbarsComponentProps['events']>;
|
||||||
|
/** 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?: OverlayScrollbarsComponentProps['defer'] | Ref<OverlayScrollbarsComponentProps['defer']>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UseOverlayScrollbarsInitialization = (
|
export type UseOverlayScrollbarsInitialization = (target: InitializationTarget) => void;
|
||||||
target: InitializationTarget
|
|
||||||
) => OverlayScrollbars;
|
|
||||||
|
|
||||||
export type UseOverlayScrollbarsInstance = () => ReturnType<
|
export type UseOverlayScrollbarsInstance = () => ReturnType<
|
||||||
OverlayScrollbarsComponentRef['osInstance']
|
OverlayScrollbarsComponentRef['osInstance']
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
const createDefer = (): Defer => {
|
||||||
|
/* c8 ignore start */
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
// mock ssr calls with "noop"
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
const noop = () => {};
|
||||||
|
return [noop, noop];
|
||||||
|
}
|
||||||
|
/* c8 ignore end */
|
||||||
|
|
||||||
|
let idleId: number;
|
||||||
|
let rafId: number;
|
||||||
|
const wnd = window;
|
||||||
|
const idleSupported = typeof wnd.requestIdleCallback === 'function';
|
||||||
|
const rAF = wnd.requestAnimationFrame;
|
||||||
|
const cAF = wnd.cancelAnimationFrame;
|
||||||
|
const rIdle = idleSupported ? wnd.requestIdleCallback : rAF;
|
||||||
|
const cIdle = idleSupported ? wnd.cancelIdleCallback : cAF;
|
||||||
|
const clear = () => {
|
||||||
|
cIdle(idleId);
|
||||||
|
cAF(rafId);
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
(callback, options) => {
|
||||||
|
clear();
|
||||||
|
idleId = rIdle(
|
||||||
|
idleSupported
|
||||||
|
? () => {
|
||||||
|
clear();
|
||||||
|
// inside idle its best practice to use rAF to change DOM for best performance
|
||||||
|
rafId = rAF(callback);
|
||||||
|
}
|
||||||
|
: callback,
|
||||||
|
typeof options === 'object' ? options : { timeout: 2233 }
|
||||||
|
);
|
||||||
|
},
|
||||||
|
clear,
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Composable for advanced usage of OverlayScrollbars. (When the OverlayScrollbarsComponent is not enough)
|
* Composable for advanced usage of OverlayScrollbars. (When the OverlayScrollbarsComponent is not enough)
|
||||||
* @param params Parameters for customization.
|
* @param params Parameters for customization.
|
||||||
@@ -39,7 +85,17 @@ export const useOverlayScrollbars = (
|
|||||||
let instance: ReturnType<UseOverlayScrollbarsInstance> = null;
|
let instance: ReturnType<UseOverlayScrollbarsInstance> = null;
|
||||||
let options: UnwrapRef<UseOverlayScrollbarsParams['options']>;
|
let options: UnwrapRef<UseOverlayScrollbarsParams['options']>;
|
||||||
let events: UnwrapRef<UseOverlayScrollbarsParams['events']>;
|
let events: UnwrapRef<UseOverlayScrollbarsParams['events']>;
|
||||||
|
let defer: UnwrapRef<UseOverlayScrollbarsParams['defer']>;
|
||||||
const paramsRef = shallowRef(params || {});
|
const paramsRef = shallowRef(params || {});
|
||||||
|
const [requestDefer, clearDefer] = createDefer();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => unref(paramsRef.value?.defer),
|
||||||
|
(currDefer) => {
|
||||||
|
defer = currDefer;
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => unref(paramsRef.value?.options),
|
() => unref(paramsRef.value?.options),
|
||||||
@@ -69,14 +125,25 @@ export const useOverlayScrollbars = (
|
|||||||
{ deep: true, immediate: true }
|
{ deep: true, immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearDefer();
|
||||||
|
instance?.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
return [
|
return [
|
||||||
(target: InitializationTarget): OverlayScrollbars => {
|
(target) => {
|
||||||
// if already initialized return the current instance
|
// if already initialized do nothing
|
||||||
if (OverlayScrollbars.valid(instance)) {
|
if (OverlayScrollbars.valid(instance)) {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (instance = OverlayScrollbars(target, options || {}, events || {}));
|
const init = () => (instance = OverlayScrollbars(target, options || {}, events || {}));
|
||||||
|
|
||||||
|
if (defer) {
|
||||||
|
requestDefer(init, defer);
|
||||||
|
} else {
|
||||||
|
init();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
() => instance,
|
() => instance,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
import { onMounted, ref, toRefs } from 'vue';
|
import { onMounted, ref, toRefs } from 'vue';
|
||||||
import { describe, test, afterEach, expect, vitest } from 'vitest';
|
import { describe, test, afterEach, expect, vitest, vi } from 'vitest';
|
||||||
import { OverlayScrollbars } from 'overlayscrollbars';
|
import { OverlayScrollbars } from 'overlayscrollbars';
|
||||||
import { fireEvent, render, screen, cleanup } from '@testing-library/vue';
|
import { fireEvent, render, screen, cleanup } from '@testing-library/vue';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { OverlayScrollbarsComponent } from '~/overlayscrollbars-vue';
|
import { OverlayScrollbarsComponent } from '~/overlayscrollbars-vue';
|
||||||
|
|
||||||
|
vi.useFakeTimers({
|
||||||
|
toFake: [
|
||||||
|
'requestAnimationFrame',
|
||||||
|
'cancelAnimationFrame',
|
||||||
|
'requestIdleCallback',
|
||||||
|
'cancelIdleCallback',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
describe('OverlayScrollbarsComponent', () => {
|
describe('OverlayScrollbarsComponent', () => {
|
||||||
afterEach(() => cleanup());
|
afterEach(() => cleanup());
|
||||||
|
|
||||||
@@ -117,6 +126,44 @@ describe('OverlayScrollbarsComponent', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('deferred initialization', () => {
|
||||||
|
test('basic defer', () => {
|
||||||
|
const { container } = render(<OverlayScrollbarsComponent defer />);
|
||||||
|
|
||||||
|
expect(OverlayScrollbars(container.firstElementChild! as HTMLElement)).toBeUndefined();
|
||||||
|
|
||||||
|
vi.advanceTimersByTime(2000);
|
||||||
|
|
||||||
|
expect(OverlayScrollbars(container.firstElementChild! as HTMLElement)).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('options defer', () => {
|
||||||
|
const { container } = render(<OverlayScrollbarsComponent defer={{ timeout: 0 }} />);
|
||||||
|
|
||||||
|
expect(OverlayScrollbars(container.firstElementChild! as HTMLElement)).toBeUndefined();
|
||||||
|
|
||||||
|
vi.advanceTimersByTime(2000);
|
||||||
|
|
||||||
|
expect(OverlayScrollbars(container.firstElementChild! as HTMLElement)).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('defer with unsupported Idle', () => {
|
||||||
|
const original = window.requestIdleCallback;
|
||||||
|
// @ts-ignore
|
||||||
|
window.requestIdleCallback = undefined;
|
||||||
|
|
||||||
|
const { container } = render(<OverlayScrollbarsComponent defer />);
|
||||||
|
|
||||||
|
expect(OverlayScrollbars(container.firstElementChild! as HTMLElement)).toBeUndefined();
|
||||||
|
|
||||||
|
vi.advanceTimersByTime(2000);
|
||||||
|
|
||||||
|
expect(OverlayScrollbars(container.firstElementChild! as HTMLElement)).toBeDefined();
|
||||||
|
|
||||||
|
window.requestIdleCallback = original;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('ref', () => {
|
test('ref', () => {
|
||||||
const osRef = ref();
|
const osRef = ref();
|
||||||
const { container } = render({
|
const { container } = render({
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
import { reactive, onMounted, ref, watch, toRaw, watchPostEffect } from 'vue';
|
import { reactive, onMounted, ref, toRaw } from 'vue';
|
||||||
import { describe, test, afterEach, expect, vitest } from 'vitest';
|
import { describe, test, afterEach, expect, vitest } from 'vitest';
|
||||||
import { render, screen, cleanup } from '@testing-library/vue';
|
import { render, screen, cleanup } from '@testing-library/vue';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { OverlayScrollbars } from 'overlayscrollbars';
|
||||||
import { useOverlayScrollbars } from '~/overlayscrollbars-vue';
|
import { useOverlayScrollbars } from '~/overlayscrollbars-vue';
|
||||||
import type { PartialOptions, EventListeners, OverlayScrollbars } from 'overlayscrollbars';
|
import type { PartialOptions, EventListeners } from 'overlayscrollbars';
|
||||||
|
|
||||||
describe('useOverlayScrollbars', () => {
|
describe('useOverlayScrollbars', () => {
|
||||||
afterEach(() => cleanup());
|
afterEach(() => {
|
||||||
|
try {
|
||||||
|
cleanup();
|
||||||
|
} catch {}
|
||||||
|
});
|
||||||
|
|
||||||
test('re-initialization', () => {
|
test('re-initialization', () => {
|
||||||
render({
|
const { unmount } = render({
|
||||||
setup() {
|
setup() {
|
||||||
const instanceRef = ref<OverlayScrollbars | null>(null);
|
const instanceRef = ref<OverlayScrollbars | null>(null);
|
||||||
const [initialize, instance] = useOverlayScrollbars();
|
const [initialize, instance] = useOverlayScrollbars();
|
||||||
@@ -18,12 +23,11 @@ describe('useOverlayScrollbars', () => {
|
|||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
const osInstance = initialize(event.target as HTMLElement);
|
initialize(event.target as HTMLElement);
|
||||||
if (instanceRef.value) {
|
if (instanceRef.value) {
|
||||||
expect(toRaw(instanceRef.value)).toBe(osInstance);
|
|
||||||
expect(toRaw(instanceRef.value)).toBe(instance());
|
expect(toRaw(instanceRef.value)).toBe(instance());
|
||||||
}
|
}
|
||||||
instanceRef.value = osInstance;
|
instanceRef.value = instance();
|
||||||
expect(toRaw(instanceRef.value)).toBe(instance());
|
expect(toRaw(instanceRef.value)).toBe(instance());
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -42,40 +46,37 @@ describe('useOverlayScrollbars', () => {
|
|||||||
userEvent.click(initializeBtn);
|
userEvent.click(initializeBtn);
|
||||||
|
|
||||||
expect(snapshot).toBe(initializeBtn.innerHTML);
|
expect(snapshot).toBe(initializeBtn.innerHTML);
|
||||||
|
|
||||||
|
expect(OverlayScrollbars(initializeBtn)).toBeDefined();
|
||||||
|
|
||||||
|
unmount();
|
||||||
|
|
||||||
|
expect(OverlayScrollbars(initializeBtn)).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('reactive params', async () => {
|
test('reactive params', async () => {
|
||||||
let osInstance: OverlayScrollbars;
|
let osInstance: OverlayScrollbars | null;
|
||||||
const onUpdated = vitest.fn();
|
const onUpdated = vitest.fn();
|
||||||
render({
|
const { unmount } = render({
|
||||||
setup() {
|
setup() {
|
||||||
const div = ref<HTMLElement | null>(null);
|
const div = ref<HTMLElement | null>(null);
|
||||||
const params = reactive<{ options?: PartialOptions; events?: EventListeners }>({});
|
const params = reactive<{ options?: PartialOptions; events?: EventListeners }>({});
|
||||||
const [initialize, instance] = useOverlayScrollbars(params);
|
const [initialize, instance] = useOverlayScrollbars(params);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
osInstance = initialize({ target: div.value! });
|
initialize({ target: div.value! });
|
||||||
|
osInstance = instance();
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
|
||||||
() => params,
|
|
||||||
() => {
|
|
||||||
if (params.events!.updated) {
|
|
||||||
instance()?.update(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<>
|
<>
|
||||||
<div ref={div} />
|
<div ref={div} />
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
params.options = {};
|
|
||||||
params.events = {};
|
params.events = {};
|
||||||
params.options!.paddingAbsolute = true;
|
|
||||||
params.events!.updated = onUpdated;
|
params.events!.updated = onUpdated;
|
||||||
|
params.options = {};
|
||||||
|
params.options!.paddingAbsolute = true;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
trigger
|
trigger
|
||||||
@@ -92,25 +93,22 @@ describe('useOverlayScrollbars', () => {
|
|||||||
|
|
||||||
expect(onUpdated).toHaveBeenCalledTimes(1);
|
expect(onUpdated).toHaveBeenCalledTimes(1);
|
||||||
expect(osInstance!.options().paddingAbsolute).toBe(true);
|
expect(osInstance!.options().paddingAbsolute).toBe(true);
|
||||||
|
|
||||||
|
unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('ref params', async () => {
|
test('ref params', async () => {
|
||||||
let osInstance: OverlayScrollbars;
|
let osInstance: OverlayScrollbars | null;
|
||||||
const onUpdated = vitest.fn();
|
const onUpdated = vitest.fn();
|
||||||
render({
|
const { unmount } = render({
|
||||||
setup() {
|
setup() {
|
||||||
const div = ref<HTMLElement | null>(null);
|
const div = ref<HTMLElement | null>(null);
|
||||||
const params = ref<{ options?: PartialOptions; events?: EventListeners } | undefined>();
|
const params = ref<{ options?: PartialOptions; events?: EventListeners } | undefined>();
|
||||||
const [initialize, instance] = useOverlayScrollbars(params);
|
const [initialize, instance] = useOverlayScrollbars(params);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
osInstance = initialize({ target: div.value! });
|
initialize({ target: div.value! });
|
||||||
});
|
osInstance = instance();
|
||||||
|
|
||||||
watchPostEffect(() => {
|
|
||||||
if (params.value?.events?.updated) {
|
|
||||||
instance()?.update(true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
@@ -139,29 +137,28 @@ describe('useOverlayScrollbars', () => {
|
|||||||
|
|
||||||
expect(onUpdated).toHaveBeenCalledTimes(1);
|
expect(onUpdated).toHaveBeenCalledTimes(1);
|
||||||
expect(osInstance!.options().paddingAbsolute).toBe(true);
|
expect(osInstance!.options().paddingAbsolute).toBe(true);
|
||||||
|
|
||||||
|
unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('ref params fields', async () => {
|
test('ref params fields', async () => {
|
||||||
let osInstance: OverlayScrollbars;
|
let osInstance: OverlayScrollbars | null;
|
||||||
const onUpdated = vitest.fn();
|
const onUpdated = vitest.fn();
|
||||||
render({
|
const { unmount } = render({
|
||||||
setup() {
|
setup() {
|
||||||
const div = ref<HTMLElement | null>(null);
|
const div = ref<HTMLElement | null>(null);
|
||||||
const options = ref<PartialOptions | undefined>();
|
const options = ref<PartialOptions | undefined>();
|
||||||
const events = ref<EventListeners | undefined>();
|
const events = ref<EventListeners | undefined>();
|
||||||
|
const defer = ref<boolean | undefined>();
|
||||||
const [initialize, instance] = useOverlayScrollbars({
|
const [initialize, instance] = useOverlayScrollbars({
|
||||||
options,
|
options,
|
||||||
events,
|
events,
|
||||||
|
defer,
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
osInstance = initialize({ target: div.value! });
|
initialize({ target: div.value! });
|
||||||
});
|
osInstance = instance();
|
||||||
|
|
||||||
watchPostEffect(() => {
|
|
||||||
if (events.value?.updated) {
|
|
||||||
instance()?.update(true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
@@ -169,10 +166,10 @@ describe('useOverlayScrollbars', () => {
|
|||||||
<div ref={div} />
|
<div ref={div} />
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
options.value = {};
|
|
||||||
events.value = {};
|
events.value = {};
|
||||||
options.value.paddingAbsolute = true;
|
|
||||||
events.value.updated = onUpdated;
|
events.value.updated = onUpdated;
|
||||||
|
options.value = {};
|
||||||
|
options.value.paddingAbsolute = true;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
trigger
|
trigger
|
||||||
@@ -189,5 +186,7 @@ describe('useOverlayScrollbars', () => {
|
|||||||
|
|
||||||
expect(onUpdated).toHaveBeenCalledTimes(1);
|
expect(onUpdated).toHaveBeenCalledTimes(1);
|
||||||
expect(osInstance!.options().paddingAbsolute).toBe(true);
|
expect(osInstance!.options().paddingAbsolute).toBe(true);
|
||||||
|
|
||||||
|
unmount();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user