Skip to content

Commit 203715c

Browse files
committed
feat: add sensor/useMedia hook
1 parent 97ec0a9 commit 203715c

File tree

7 files changed

+86
-9
lines changed

7 files changed

+86
-9
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ and then:
6969
* [ ] `useIdle`: tracks whether user is being inactive
7070
* [ ] `useIntersection`: tracks an HTML element's intersection
7171
* [ ] `useEvent`: subscribe to events
72-
* [ ] `useMedia`: tracks state of a CSS media query
72+
* [x] [`useMedia`](./src/hooks/sensor/useMedia/doc.md): tracks state of a CSS media query
7373
* [ ] `useMediaDevices`: tracks connected hardware devices
7474
* [ ] `useMotion`: tracks state of device's motion sensor
7575
* [x] [`useMouse`](./src/hooks/sensor/useMouse/doc.md): tracks state of mouse position
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { storiesOf } from '@storybook/vue'
2+
import { createComponent } from '@vue/composition-api'
3+
import Doc from '../../../__stories__/components/Doc'
4+
import { useMedia } from '../../..'
5+
6+
const Demo = createComponent({
7+
setup() {
8+
const isWide = useMedia('(min-width: 480px)')
9+
return { isWide }
10+
},
11+
render() {
12+
const { isWide } = this
13+
return <div>Screen is wide(min-width: 480px): {isWide ? 'Yes' : 'No'}</div>
14+
}
15+
})
16+
17+
const Docs = () => <Doc md={require('./doc.md')}></Doc>
18+
19+
storiesOf('Sensor|useMedia', module)
20+
.add('Docs', () => Docs as any)
21+
.add('Demo', () => Demo)

src/hooks/sensor/useMedia/doc.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# useMedia
2+
3+
Vue hook that tracks state of a CSS media query.
4+
5+
> Browser environment is required
6+
7+
## Usage
8+
9+
```jsx
10+
import { createComponent } from '@vue/composition-api'
11+
import { useMouse } from 'vuses'
12+
13+
const Demo = createComponent({
14+
setup() {
15+
const isWide = useMedia('(min-width: 480px)')
16+
return { isWide }
17+
},
18+
render() {
19+
const { isWide } = this
20+
return <div>Screen is wide(min-width: 480px): {isWide ? 'Yes' : 'No'}</div>
21+
}
22+
})
23+
```
24+
25+
## Reference
26+
27+
```typescript
28+
function useMedia(query: string): Ref<boolean>
29+
```

src/hooks/sensor/useMedia/index.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { ref, onMounted, onUnmounted, Ref } from '@vue/composition-api'
2+
import {
3+
checkBrowser,
4+
addEventListener,
5+
removeEventListener
6+
} from '../../../utils'
7+
8+
export default function useMedia(query: string): Ref<boolean> {
9+
checkBrowser(useMedia.name)
10+
11+
const state = ref(window.matchMedia(query).matches)
12+
let mounted = true
13+
let mql: MediaQueryList = window.matchMedia(query)
14+
15+
const update = () => {
16+
if (!mounted) return
17+
state.value = !!mql.matches
18+
}
19+
20+
onMounted(() => {
21+
update()
22+
addEventListener(mql, 'change', update)
23+
})
24+
25+
onUnmounted(() => {
26+
mounted = false
27+
removeEventListener(mql, 'change', update)
28+
})
29+
30+
return state
31+
}

src/hooks/sensor/useMouse/demo.story.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import { storiesOf } from '@storybook/vue'
2-
import {
3-
createComponent,
4-
reactive,
5-
computed,
6-
onMounted
7-
} from '@vue/composition-api'
2+
import { createComponent } from '@vue/composition-api'
83
import Doc from '../../../__stories__/components/Doc'
94
import { useMouse } from '../../..'
105

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export { default as useWindowScroll } from './hooks/sensor/useWindowScroll'
1111
export { default as useGeolocation } from './hooks/sensor/useGeolocation'
1212
export { default as useMouse } from './hooks/sensor/useMouse'
1313
export { default as useBattery } from './hooks/sensor/useBattery'
14+
export { default as useMedia } from './hooks/sensor/useMedia'
1415

1516
// Side Effect Hooks
1617
export { default as useTitle } from './hooks/sideEffect/useTitle'

src/utils/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export const checkBrowser = (ctx = '') => {
3535
}
3636

3737
export const addEventListener = (
38-
el: Element | Window | PermissionStatus | Document | BatteryManager,
38+
el: EventTarget,
3939
event: string,
4040
handler: EventListener,
4141
options?: AddEventListenerOptions
@@ -44,7 +44,7 @@ export const addEventListener = (
4444
}
4545

4646
export const removeEventListener = (
47-
el: Element | Window | PermissionStatus | Document | BatteryManager,
47+
el: EventTarget,
4848
event: string,
4949
handler: EventListener,
5050
options?: EventListenerOptions

0 commit comments

Comments
 (0)