forked from phc/website
1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
website/src/client/lib/util.ts

70 lines
2.0 KiB
TypeScript

import { useEffect, useState } from 'preact/hooks'
export const trottleDebounce = <T extends any[], R>(
fn: (...args: T) => R,
delay: number,
options: { leading?: boolean; trailing?: boolean } = {},
): ((...args: T) => R | undefined) => {
let lastCall = 0
let lastResult: R | undefined
let lastArgs: T | undefined
let timeout: NodeJS.Timeout | undefined
const leading = options.leading ?? true
const trailing = options.trailing ?? true
return (...args: T): R | undefined => {
lastArgs = args
if (leading && Date.now() - lastCall >= delay) {
lastCall = Date.now()
lastResult = fn(...args)
} else {
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(() => {
if (trailing && lastArgs) {
lastCall = Date.now()
lastResult = fn(...lastArgs)
}
}, delay)
}
return lastResult
}
}
export type ClassValue = string | ClassValue[] | Record<string, boolean> | false | undefined
export function clsx(...args: ClassValue[]): string {
return args
.flatMap(arg => {
if (typeof arg === 'string') {
return arg
} else if (Array.isArray(arg)) {
return clsx(...arg)
} else if (typeof arg === 'boolean') {
return []
} else if (typeof arg === 'object') {
return Object.entries(arg).flatMap(([key, value]) => (value ? key : []))
} else {
return []
}
})
.join(' ')
}
export const isMobile = () => {
const [windowWidth, setWindowWidth] = useState(0)
useEffect(() => {
setWindowWidth(window.innerWidth)
const handleResize = () => setWindowWidth(window.innerWidth)
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])
return windowWidth < 1024
}