Skip to content

Commit c2e6df8

Browse files
studnitzlogaretm
authored andcommitted
feat: add useDocumentVisibility composable function (#23)
* Make scripts executable * Add event listener helpers * Add useDocumentVisibility function * Add docs for useDocumentVisibility * Allow additional options for useEventListener * Refactor event listener helpers
1 parent 2dd4aec commit c2e6df8

File tree

9 files changed

+104
-0
lines changed

9 files changed

+104
-0
lines changed

docs/.vuepress/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ module.exports = {
6060
'device-light',
6161
'device-motion',
6262
'device-orientation',
63+
'document-visibility',
6364
'fetch',
6465
'fullscreen',
6566
'geolocation',

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ npm install @vue/composition-api vue-use-web
4242
- [Device Light](./guide/device-light.md).
4343
- [Device Motion](./guide/device-motion.md).
4444
- [Device Orientation](./guide/device-orientation.md).
45+
- [Document Visibility](./document-visibility.md)
4546
- [Fetch API](./guide/fetch.md).
4647
- [Full-screen](./guide/fullscreen.md).
4748
- [Geo-location API](./guide/geolocation.md).

docs/guide/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ These are the currently implemented Web APIs and the planned ones.
2626
- [Device Light](./device-light.md).
2727
- [Device Motion](./device-motion.md).
2828
- [Device Orientation](./device-orientation.md).
29+
- [Document Visibility](./document-visibility.md)
2930
- [Fetch API](./fetch.md).
3031
- [Full-screen](./fullscreen.md).
3132
- [Geo-location API](./geolocation.md).

docs/guide/document-visibility.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Media Query
2+
3+
> The [`Document.visibilityState`](https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState) read-only property returns the visibility of the document, that is in which context this element is now visible. It is useful to know if the document is in the background or an invisible tab, or only loaded for pre-rendering. Possible values are:
4+
5+
## State
6+
7+
```js
8+
import { useDocumentVisibility } from 'vue-use-web';
9+
10+
const pageIsVisible = useDocumentVisibility();
11+
```
12+
13+
`useDocumentVisibility` only returns a single value which is a boolean.
14+
15+
| State | Type | Description |
16+
| --------- | -------------- | ---------------------------------------------------------- |
17+
| isVisible | `Ref<boolean>` | If the page is currently visible (not in a background tab) |
18+
19+
## Example
20+
21+
```vue
22+
<template>
23+
<h1>Page is currently visible: {{ isVisible }}</h1>
24+
</template>
25+
26+
<script>
27+
import { useMedia } from 'vue-use-web';
28+
import { watch } from '@vue/composition-api'
29+
30+
31+
export default {
32+
setup() {
33+
const isVisible = useDocumentVisibility()
34+
35+
watch(() => console.log(isVisible.value))
36+
37+
return { isVisible }
38+
}
39+
};
40+
</script>
41+
```
42+
43+
## Demo
44+
45+
TODO: Add cool live example!

scripts/defs.sh

100644100755
File mode changed.

scripts/deploy.sh

100644100755
File mode changed.

src/DocumentVisibility.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { ref, Ref } from '@vue/composition-api';
2+
import { hasWindow, useDocumentEventListener } from './utils';
3+
4+
/**
5+
* Tracks visibility of the page.
6+
*
7+
* @returns True if the document is currently visible.
8+
*
9+
* @example
10+
* setup() {
11+
* const isVisible = useDocumentVisibility()
12+
* watch(() => console.log(isVisible))
13+
* }
14+
*
15+
*/
16+
export function useDocumentVisibility(): Ref<boolean> {
17+
const documentIsVisible = () => document.visibilityState === 'visible';
18+
19+
const isVisible: Ref<boolean> = ref(hasWindow ? documentIsVisible() : true);
20+
21+
useDocumentEventListener('visibilitychange', () => {
22+
isVisible.value = documentIsVisible();
23+
});
24+
25+
return isVisible;
26+
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export * from './Clipboard';
33
export * from './DeviceLight';
44
export * from './DeviceMotion';
55
export * from './DeviceOrientation';
6+
export * from './DocumentVisibility';
67
export * from './Fetch';
78
export * from './FullScreen';
89
export * from './Geolocation';

src/utils.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { onMounted, onUnmounted } from '@vue/composition-api';
2+
13
export function throttle<T extends (...args: any[]) => void>(wait: number, fn: T): T {
24
if (wait === 0) {
35
return fn;
@@ -17,3 +19,30 @@ export function throttle<T extends (...args: any[]) => void>(wait: number, fn: T
1719
timeout = setTimeout(later, wait) as any;
1820
}) as T;
1921
}
22+
23+
export const hasWindow = typeof window !== 'undefined';
24+
25+
export function useEventListener(
26+
element: EventTarget,
27+
type: string,
28+
listener: EventListenerOrEventListenerObject,
29+
options?: EventListenerOptions
30+
) {
31+
onMounted(() => {
32+
element.addEventListener(type, listener, options);
33+
});
34+
35+
onUnmounted(() => {
36+
element.removeEventListener(type, listener, options);
37+
});
38+
}
39+
40+
const eventListenerFor = (element: EventTarget) => (
41+
type: string,
42+
listener: EventListenerOrEventListenerObject,
43+
options?: EventListenerOptions
44+
) => useEventListener(element, type, listener, options);
45+
46+
export const useDocumentEventListener = eventListenerFor(document);
47+
48+
export const useWindowEventListener = eventListenerFor(window);

0 commit comments

Comments
 (0)