/* eslint-disable no-redeclare */ import { Draft } from 'immer' import { useImmer } from 'use-immer' import { useRef, useEffect, useState, useMemo } from 'react' import { noop } from '@lib/helper' export function useObject> (initialValue: T) { const [copy, rawSet] = useImmer(initialValue) const set = useMemo(() => { function set (data: Partial): void function set (f: (draft: Draft) => void | T): void function set> (key: K, value: Draft[K]): void function set> (data: any, value?: Draft[K]): void { if (typeof data === 'string') { rawSet(draft => { const key = data as K const v = value draft[key] = v! }) } else if (typeof data === 'function') { rawSet(data) } else if (typeof data === 'object') { rawSet((draft: Draft) => { const obj = data as Draft for (const key of Object.keys(obj)) { const k = key as keyof Draft draft[k] = obj[k] } }) } } return set }, [rawSet]) return [copy, set] as [T, typeof set] } export function useInterval (callback: () => void, delay: number) { const savedCallback = useRef(noop) useEffect(() => { savedCallback.current = callback }, [callback]) useEffect( () => { const handler = () => savedCallback.current() if (delay !== null) { const id = setInterval(handler, delay) return () => clearInterval(id) } }, [delay], ) } export function useRound (list: T[], defidx = 0) { if (list.length < 2) { throw new Error('List requires at least two elements') } const [state, setState] = useState(defidx) function next () { setState((state + 1) % list.length) } const current = useMemo(() => list[state], [list, state]) return { current, next } } export function useVisible (initial = false) { const [visible, setVisible] = useState(initial) function hide () { setVisible(false) } function show () { setVisible(true) } return { visible, hide, show } }