@codeleap/web 3.21.1 → 3.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/lib/hooks.ts +76 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codeleap/web",
3
- "version": "3.21.1",
3
+ "version": "3.21.2",
4
4
  "main": "src/index.ts",
5
5
  "repository": {
6
6
  "url": "https://github.com/codeleap-uk/internal-libs-monorepo.git",
package/src/lib/hooks.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { AnyFunction, onMount, onUpdate, range, useUncontrolled } from '@codeleap/common'
2
- import { useCallback, useMemo, useRef, useState } from 'react'
1
+ import { AnyFunction, onMount, onUpdate, range, TypeGuards, useUncontrolled } from '@codeleap/common'
2
+ import React, { useCallback, useMemo, useRef, useState } from 'react'
3
3
  import { v4 } from 'uuid'
4
4
  import { easeInOut, EasingFunction, AnimationProps, useAnimate, useAnimation, animate } from 'framer-motion'
5
+ import { globalHistory } from '@reach/router'
5
6
 
6
7
  export function useWindowSize() {
7
8
  const [size, setSize] = useState([])
@@ -352,3 +353,76 @@ export function useAnimatedVariantStyles<T extends Record<string|number|symbol,
352
353
 
353
354
  return animated
354
355
  }
356
+
357
+ type UseWindowFocusOptions = {
358
+ onFocus?: AnyFunction
359
+ onBlur?: AnyFunction
360
+ }
361
+
362
+ export const useWindowFocus = (options: UseWindowFocusOptions = {}, deps: Array<any> = []): boolean => {
363
+ const [focused, setFocused] = useState(true)
364
+
365
+ const onFocus = () => {
366
+ setFocused(true)
367
+ if (TypeGuards.isFunction(options?.onFocus)) options?.onFocus()
368
+ }
369
+
370
+ const onBlur = () => {
371
+ setFocused(false)
372
+ if (TypeGuards.isFunction(options?.onBlur)) options?.onBlur()
373
+ }
374
+
375
+ useEffect(() => {
376
+ window.addEventListener('focus', onFocus)
377
+ window.addEventListener('blur', onBlur)
378
+
379
+ return () => {
380
+ window.removeEventListener('focus', onFocus)
381
+ window.removeEventListener('blur', onBlur)
382
+ }
383
+ }, deps)
384
+
385
+ return focused
386
+ }
387
+
388
+ export const usePageExitBlocker = (
389
+ handler: (willLeavePage: boolean) => void,
390
+ deps: Array<any> = [],
391
+ message: string = 'Are you sure you want to leave?'
392
+ ) => {
393
+ const handleBeforeUnload = (event: BeforeUnloadEvent) => {
394
+ if (!event) return null
395
+
396
+ event?.preventDefault()
397
+ event.returnValue = ''
398
+ return
399
+ }
400
+
401
+ React.useEffect(() => {
402
+ if (!window) return null
403
+
404
+ window.addEventListener('beforeunload', handleBeforeUnload)
405
+
406
+ return () => {
407
+ window.removeEventListener('beforeunload', handleBeforeUnload)
408
+ }
409
+ }, deps)
410
+
411
+ React.useEffect(() => {
412
+ return globalHistory.listen((args) => {
413
+ if (!window) return null
414
+
415
+ const historyPathname = args?.location?.pathname
416
+ const windowPathname = window?.location?.pathname
417
+
418
+ const isPopAction = args?.action === 'POP'
419
+ const isLeaveAction = args?.action === 'PUSH' && !historyPathname?.includes(windowPathname)
420
+
421
+ if (isLeaveAction || isPopAction) {
422
+ const willLeavePage = window.confirm(message)
423
+
424
+ handler?.(willLeavePage)
425
+ }
426
+ })
427
+ }, deps)
428
+ }