diff --git a/docs/useVibrate.md b/docs/useVibrate.md new file mode 100644 index 00000000..e69de29b diff --git a/src/__stories__/useVibrate.story.tsx b/src/__stories__/useVibrate.story.tsx new file mode 100644 index 00000000..f521771c --- /dev/null +++ b/src/__stories__/useVibrate.story.tsx @@ -0,0 +1,20 @@ +import { storiesOf } from '@storybook/react'; +import * as React from 'react'; +import { useVibrate, useToggle } from '..'; +import ShowDocs from './util/ShowDocs'; + +const Demo = () => { + const [vibrating, toggleVibrating] = useToggle(false); + + useVibrate(vibrating, [300, 100, 200, 100, 1000, 300]); + + return ( +
+ +
+ ); +}; + +storiesOf('UI|useVibrate', module) + .add('Docs', () => ) + .add('Demo', () => ); diff --git a/src/index.ts b/src/index.ts index 65872134..745dae63 100644 --- a/src/index.ts +++ b/src/index.ts @@ -86,6 +86,7 @@ export { default as useUnmount } from './useUnmount'; export { default as useUpdate } from './useUpdate'; export { default as useUpdateEffect } from './useUpdateEffect'; export { default as useUpsert } from './useUpsert'; +export { default as useVibrate } from './useVibrate'; export { default as useVideo } from './useVideo'; export { default as useStateValidator } from './useStateValidator'; export { useWait, Waiter } from './useWait'; diff --git a/src/useVibrate.ts b/src/useVibrate.ts new file mode 100644 index 00000000..23f7c619 --- /dev/null +++ b/src/useVibrate.ts @@ -0,0 +1,37 @@ +import { useEffect } from 'react'; + +export type VibrationPattern = number | number[]; + +const isVibrationApiSupported = typeof navigator === 'object' && 'vibrate' in navigator; + +const useVibrateMock = () => {}; + +function useVibrate(enabled: boolean = true, pattern: VibrationPattern = [1000, 1000], loop: boolean = true): void { + useEffect(() => { + let interval; + + if (enabled) { + navigator.vibrate(pattern); + + if (loop) { + const duration = pattern instanceof Array ? pattern.reduce((a, b) => a + b) : (pattern as number); + + interval = setInterval(() => { + navigator.vibrate(pattern); + }, duration); + } + } + + return () => { + if (enabled) { + navigator.vibrate(0); + + if (loop) { + clearInterval(interval); + } + } + }; + }, [enabled]); +} + +export default isVibrationApiSupported ? useVibrate : useVibrateMock;