helpers.ts56 lines · main
1'use client'
2
3import { useSyncExternalStore } from 'react'
4import type * as React from 'react'
5
6export const detectBrowser = () => {
7 if (!navigator) return undefined
8
9 if (navigator.userAgent.indexOf('Chrome') !== -1) {
10 return 'Chrome'
11 } else if (navigator.userAgent.indexOf('Firefox') !== -1) {
12 return 'Firefox'
13 } else if (navigator.userAgent.indexOf('Safari') !== -1) {
14 return 'Safari'
15 }
16}
17
18export const isBrowser = typeof window !== 'undefined'
19
20const prefersReducedMotionMediaQuery =
21 isBrowser && window.matchMedia('(prefers-reduced-motion: reduce)')
22
23/**
24 * @returns boolean value If the user has expressed their preference for reduced motion.
25 */
26export const useReducedMotion = (): boolean => {
27 if (!prefersReducedMotionMediaQuery) return false
28 return useSyncExternalStore(
29 (callback) => {
30 prefersReducedMotionMediaQuery.addEventListener('change', callback)
31 return () => {
32 prefersReducedMotionMediaQuery.removeEventListener('change', callback)
33 }
34 },
35 () => prefersReducedMotionMediaQuery.matches,
36 () => false
37 )
38}
39
40export function ensurePlatformSuffix(apiUrl: string) {
41 return apiUrl.endsWith('/platform') ? apiUrl : `${apiUrl}/platform`
42}
43
44export function mergeRefs<T>(...refs: React.Ref<T>[]): React.RefCallback<T> {
45 return (value) => {
46 refs.forEach((ref) => {
47 if (typeof ref === 'function') {
48 ref(value)
49 } else if (ref !== null) {
50 if (typeof ref === 'object' && ref !== null && 'current' in ref) {
51 ;(ref as any).current = value
52 }
53 }
54 })
55 }
56}