Skip to content

Commit 80dad43

Browse files
authored
Merge pull request #6 from microcipcip/feature/useIdle
Feature/use idle
2 parents 1c546a5 + 5923529 commit 80dad43

File tree

24 files changed

+418
-13
lines changed

24 files changed

+418
-13
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ Vue.use(VueCompositionAPI);
6363
[![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-usegeolocation--demo)
6464
- [`useHover`](./src/components/useHover/stories/useHover.md) — tracks mouse hover state of a given element.
6565
[![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-usehover--demo)
66+
- [`useIdle`](./src/components/useIdle/stories/useIdle.md) — tracks whether user is being inactive.
67+
[![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-useidle--demo)
6668
- [`useIntersection`](./src/components/useIntersection/stories/useIntersection.md) — tracks intersection of target element with an ancestor element.
6769
[![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-useintersection--demo)
6870
[![Demo](https://img.shields.io/badge/advanced_demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-useintersection--advanced-demo)

package-lock.json

Lines changed: 50 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
"@storybook/vue": "^5.3.13",
9595
"@types/jest": "^23.3.2",
9696
"@types/node": "^10.11.0",
97+
"@types/throttle-debounce": "^2.1.0",
9798
"@typescript-eslint/eslint-plugin": "^2.18.0",
9899
"@typescript-eslint/parser": "^2.18.0",
99100
"@vue/composition-api": "^0.3.4",
@@ -136,5 +137,7 @@
136137
"vue-loader": "^15.8.3",
137138
"vue-template-compiler": "^2.6.11"
138139
},
139-
"dependencies": {}
140+
"dependencies": {
141+
"throttle-debounce": "^2.1.0"
142+
}
140143
}

src/components/useClickAway/useClickAway.spec.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { mount } from '@src/helpers/test'
22
import { ref } from '@src/api'
33
import { useClickAway } from '@src/vue-use-kit'
44

5+
afterEach(() => {
6+
jest.clearAllMocks()
7+
})
8+
59
const testComponent = () => ({
610
template: `
711
<div id="outside-el">
@@ -29,10 +33,17 @@ describe('useClickAway', () => {
2933
const wrapper = mount(testComponent())
3034
await wrapper.vm.$nextTick()
3135
expect(addEventListenerSpy).toHaveBeenCalled()
36+
expect(addEventListenerSpy).toBeCalledWith(
37+
'mousedown',
38+
expect.any(Function)
39+
)
3240

3341
// Destroy instance to check if the remove event listener is being called
3442
wrapper.destroy()
3543
expect(removeEventListenerSpy).toHaveBeenCalled()
36-
addEventListenerSpy.mockClear()
44+
expect(removeEventListenerSpy).toBeCalledWith(
45+
'mousedown',
46+
expect.any(Function)
47+
)
3748
})
3849
})

src/components/useFullscreen/useFullscreen.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { useFullscreen } from '@src/vue-use-kit'
55
// This feature is difficult to test therefore
66
// I've only written a simple test
77

8+
afterEach(() => {
9+
jest.clearAllMocks()
10+
})
11+
812
const testComponent = () => ({
913
template: `
1014
<div id="divRef" ref="divRef">

src/components/useHover/useHover.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { mount } from '@src/helpers/test'
22
import { ref } from '@src/api'
33
import { useHover } from '@src/vue-use-kit'
44

5+
afterEach(() => {
6+
jest.clearAllMocks()
7+
})
8+
59
const testComponent = () => ({
610
template: `
711
<div id="isHovered" v-if="isHovered"></div>
@@ -22,9 +26,17 @@ describe('useHover', () => {
2226
)
2327
const wrapper = mount(testComponent())
2428
expect(addEventListenerSpy).toHaveBeenCalled()
29+
expect(addEventListenerSpy).toBeCalledWith(
30+
'mouseenter',
31+
expect.any(Function)
32+
)
2533
expect(removeEventListenerSpy).not.toHaveBeenCalled()
2634
wrapper.destroy()
2735
expect(removeEventListenerSpy).toHaveBeenCalled()
36+
expect(removeEventListenerSpy).toBeCalledWith(
37+
'mouseenter',
38+
expect.any(Function)
39+
)
2840
})
2941

3042
it('should return isHovered false by default', () => {

src/components/useIdle/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './useIdle'
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<template>
2+
<table class="table is-fullwidth">
3+
<thead>
4+
<tr>
5+
<th>Prop</th>
6+
<th>Value</th>
7+
</tr>
8+
</thead>
9+
<tbody>
10+
<tr>
11+
<td>isIdle</td>
12+
<td class="idle" :class="{ '-is-idle': isIdle }">{{ isIdle }}</td>
13+
</tr>
14+
<tr>
15+
<td colspan="2">
16+
<button
17+
class="button is-primary"
18+
@click="startTracking"
19+
v-if="!isTracking"
20+
>
21+
Start tracking idle status
22+
</button>
23+
<button class="button is-danger" @click="stopTracking" v-else>
24+
Stop tracking idle status
25+
</button>
26+
</td>
27+
</tr>
28+
</tbody>
29+
</table>
30+
</template>
31+
32+
<script lang="ts">
33+
import Vue from 'vue'
34+
import { ref } from '@src/api'
35+
import { useIdle } from '@src/vue-use-kit'
36+
37+
export default Vue.extend({
38+
name: 'UseIdleDemo',
39+
setup() {
40+
const { isIdle, start, stop } = useIdle(2500)
41+
42+
const isTracking = ref(true)
43+
const startTracking = () => {
44+
isTracking.value = true
45+
start()
46+
}
47+
const stopTracking = () => {
48+
isTracking.value = false
49+
stop()
50+
}
51+
52+
return { isIdle, isTracking, startTracking, stopTracking }
53+
}
54+
})
55+
</script>
56+
57+
<style scoped>
58+
.idle {
59+
color: #fff;
60+
background: #981105;
61+
}
62+
63+
.idle.-is-idle {
64+
color: #fff;
65+
background: #209817;
66+
}
67+
</style>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# useIdle
2+
3+
Vue function that tracks whether user is being inactive.
4+
5+
## Reference
6+
7+
```typescript
8+
useIdle(
9+
ms?: number,
10+
events?: string[],
11+
runOnMount?: boolean
12+
): {
13+
isIdle: Ref<boolean>;
14+
start: () => void;
15+
stop: () => void;
16+
}
17+
```
18+
19+
### Parameters
20+
21+
- `ms: number` milliseconds to wait before deciding whether the user is being idle
22+
- `events: string[]` list of events to track the user for
23+
- `runOnMount: boolean` whether to start tracking idle state on mount, `true` by default
24+
25+
### Returns
26+
27+
- `isIdle: Ref<boolean>` it is `true` when the user is idle, `false` otherwise
28+
- `start: Function` the function used for start tracking the user's idle state
29+
- `stop: Function` the function used for stop tracking the user's idle state
30+
31+
## Usage
32+
33+
```html
34+
<template>
35+
<div>
36+
<p>isIdle: {{ isIdle }}</p>
37+
<button @click="startTracking" v-if="!isTracking">Start tracking</button>
38+
<button @click="stopTracking" v-else>Stop tracking</button>
39+
</div>
40+
</template>
41+
42+
<script lang="ts">
43+
import Vue from 'vue'
44+
import { useIdle } from 'vue-use-kit'
45+
46+
export default Vue.extend({
47+
name: 'UseIdleDemo',
48+
setup() {
49+
const { isIdle, start, stop } = useIdle(2500)
50+
51+
const isTracking = ref(true)
52+
const startTracking = () => {
53+
isTracking.value = true
54+
start()
55+
}
56+
const stopTracking = () => {
57+
isTracking.value = false
58+
stop()
59+
}
60+
61+
return { isIdle, isTracking, startTracking, stopTracking }
62+
}
63+
})
64+
</script>
65+
```
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { storiesOf } from '@storybook/vue'
2+
import path from 'path'
3+
import StoryTitle from '@src/helpers/StoryTitle.vue'
4+
import UseIdleDemo from './UseIdleDemo.vue'
5+
6+
const functionName = 'useIdle'
7+
const functionPath = path.resolve(__dirname, '..')
8+
const notes = require(`./${functionName}.md`).default
9+
10+
const basicDemo = () => ({
11+
components: { StoryTitle, demo: UseIdleDemo },
12+
template: `
13+
<div class="container">
14+
<story-title
15+
function-path="${functionPath}"
16+
source-name="${functionName}"
17+
demo-name="UseIdleDemo.vue"
18+
>
19+
<template v-slot:title></template>
20+
<template v-slot:intro></template>
21+
</story-title>
22+
<demo />
23+
</div>`
24+
})
25+
26+
storiesOf('sensors|useIdle', module)
27+
.addParameters({ notes })
28+
.add('Demo', basicDemo)

0 commit comments

Comments
 (0)