1- import { useEffect , useState } from 'react' ;
1+ import { useEffect , useRef , useState } from 'react' ;
22
3- import { isClient } from '@/utils/helpers' ;
3+ /** The use vibrate pattern type */
4+ export type UseVibratePattern = number | number [ ] ;
45
5- /** The use vibration params */
6+ /** The use vibrate params type */
67export interface UseVibrateParams {
8+ /** Time in milliseconds between vibrations */
9+ interval ?: number ;
710 /** Pattern for vibration */
8- pattern : number | number [ ] ;
9- /** Alternate way to enable vibration */
10- enabled ?: boolean ;
11- /** Indicates thar vibration will be endless */
12- loop ?: boolean ;
11+ pattern : UseVibratePattern ;
1312}
1413
15- /** The use vibration options */
16- export interface UseVibrateOptions {
17- /** Alternate way to enable vibration */
18- enabled ?: boolean ;
19- /** Indicates thar vibration will be endless */
20- loop ?: boolean ;
21- }
22-
23- /** The use vibration return type */
14+ /** The use vibrate return type */
2415export interface UseVibrateReturn {
25- /** Indicates that the device supports Vibration API */
26- isSupported : boolean ;
27- /** Indicates that the device is vibrating */
28- isVibrating : boolean ;
29- /** Start vibration function */
30- vibrate : ( pattern ?: number | number [ ] ) => void ;
31- /** Stop vibration function */
16+ /** The support indicator */
17+ supported : boolean ;
18+ /** The vibrating indicator */
19+ vibrating : boolean ;
20+ /** The pause function */
21+ pause : ( ) => void ;
22+ /** The resume function */
23+ resume : ( ) => void ;
24+ /** The stop function */
3225 stop : ( ) => void ;
26+ /** The vibrate function */
27+ vibrate : ( pattern ?: UseVibratePattern ) => void ;
3328}
3429
35- export type UseVibrate = {
36- ( pattern : number | number [ ] , options ?: UseVibrateOptions ) : UseVibrateReturn ;
37- ( { pattern, loop, enabled } : UseVibrateParams , options ?: never ) : UseVibrateReturn ;
38- } ;
39-
40- let interval : NodeJS . Timeout ;
4130/**
4231 * @name useVibrate
43- * @description - Hook that provides Vibrate API
32+ * @description - Hook that provides vibrate api
4433 * @category Browser
4534 *
4635 * @overload
@@ -50,80 +39,48 @@ let interval: NodeJS.Timeout;
5039 * @returns {UseVibrateReturn } An object containing support indicator, start vibration and stop vibration functions
5140 *
5241 * @example
53- * const { isSupported, isVibrating, vibrate, stop } = useVibrate(1000);
54- *
55- * @overload
56- * @param {(number|number[]) } params.pattern Pattern for vibration
57- * @param {boolean } [params.loop] Indicates thar vibration will be endless
58- * @param {boolean } [params.enabled] Alternate way to enable vibration
59- * @returns {UseVibrateReturn } An object containing support indicator, vibrating indicator, start vibration and stop vibration functions
60- *
61- * @example
62- * const { isSupported, isVibrating, vibrate, stop } = useVibrate({pattern: [200, 100, 200], loop: true});
63- * */
64- export const useVibrate : UseVibrate = ( ...params ) => {
65- const pattern =
66- typeof params [ 0 ] === 'number' || Array . isArray ( params [ 0 ] ) ? params [ 0 ] : params [ 0 ] ?. pattern ;
67- const { loop, enabled } =
68- typeof params [ 0 ] === 'number' || Array . isArray ( params [ 0 ] ) ? params [ 1 ] ?? { } : params [ 0 ] ?? { } ;
69-
70- const [ isSupported , setIsSupported ] = useState ( false ) ;
71- const [ isVibrating , setIsVibrating ] = useState ( false ) ;
72-
73- useEffect ( ( ) => {
74- if ( isClient && navigator && 'vibrate' in navigator ) {
75- setIsSupported ( true ) ;
76- }
77- } , [ ] ) ;
78-
79- const vibrate = ( curPattern = pattern ) => {
80- if ( ! isSupported || isVibrating ) return ;
81-
82- const duration = Array . isArray ( curPattern ) ? curPattern . reduce ( ( a , b ) => a + b ) : curPattern ;
83-
84- setIsVibrating ( true ) ;
85- navigator . vibrate ( curPattern ) ;
86-
87- if ( loop ) {
88- interval = setInterval ( ( ) => {
89- navigator . vibrate ( curPattern ) ;
90- } , duration ) ;
91- } else {
92- setTimeout ( ( ) => {
93- setIsVibrating ( false ) ;
94- } , duration ) ;
95- }
42+ * const { supported, vibrating, vibrate, stop } = useVibrate(1000);
43+ */
44+ export const useVibrate = ( params : UseVibrateParams ) => {
45+ const supported = typeof navigator !== 'undefined' && 'vibrate' in navigator ;
46+
47+ const interval = params . interval ?? 0 ;
48+ const intervalIdRef = useRef < ReturnType < typeof setInterval > > ( ) ;
49+ const [ vibrating , setVibrating ] = useState ( false ) ;
50+
51+ const vibrate = ( pattern : UseVibratePattern = params . pattern ) => {
52+ if ( ! supported ) return ;
53+ navigator . vibrate ( pattern ) ;
54+ setVibrating ( true ) ;
9655 } ;
9756
9857 const stop = ( ) => {
99- if ( ! isSupported ) return ;
58+ if ( ! supported ) return ;
10059
101- setIsVibrating ( false ) ;
60+ setVibrating ( false ) ;
10261 navigator . vibrate ( 0 ) ;
10362
104- if ( loop ) {
105- clearInterval ( interval ) ;
106- }
63+ if ( intervalIdRef . current ) clearInterval ( intervalIdRef . current ) ;
10764 } ;
10865
109- useEffect ( ( ) => {
110- if ( ! isSupported || isVibrating ) return ;
66+ const pause = ( ) => {
67+ if ( ! supported ) return ;
68+ if ( intervalIdRef . current ) clearInterval ( intervalIdRef . current ) ;
69+ } ;
11170
112- if ( enabled ) {
113- vibrate ( ) ;
114- }
71+ const resume = ( ) => {
72+ if ( ! supported ) return ;
73+ if ( intervalIdRef . current ) clearInterval ( intervalIdRef . current ) ;
74+ intervalIdRef . current = setInterval ( vibrate , interval ) ;
75+ } ;
11576
77+ useEffect ( ( ) => {
78+ if ( ! supported || typeof params . interval === 'undefined' ) return ;
79+ intervalIdRef . current = setInterval ( vibrate , interval ) ;
11680 return ( ) => {
117- if ( enabled ) {
118- setIsVibrating ( false ) ;
119- navigator . vibrate ( 0 ) ;
120-
121- if ( loop ) {
122- clearInterval ( interval ) ;
123- }
124- }
81+ clearInterval ( intervalIdRef . current ) ;
12582 } ;
126- } , [ enabled ] ) ;
83+ } , [ params . interval , params . pattern ] ) ;
12784
128- return { isSupported , vibrate, stop, isVibrating } as const ;
85+ return { supported , vibrate, stop, vibrating , pause , resume } ;
12986} ;
0 commit comments