/** * Useful utilities */ import { MutableRefObject, useEffect, useLayoutEffect, useRef, useState, } from "react"; import { Observable, Subject } from "rxjs"; import { map } from "rxjs/operators"; /** * Returns the first argument it receives. */ export const identity = (value: T): T => value; /** * Maps an Observable of Arraylike to an Observable * of the first item. * * Example: * * ```typescript * const text$ = useObservable(pluckFirst, [props.text]) * ``` * * @param inputs$ An Observable of array-like. * */ export const pluckFirst = >( inputs$: Observable ): Observable => map(input => input[0])(inputs$); /** * Maps an Observable of DOM events to an Observable * of the currentTarget value. * * Example: * * ```typescript * const [onChange, textChange$] = useObservableCallback< * string, * React.FormEvent * >(pluckCurrentTargetValue) * ``` * */ export const pluckCurrentTargetValue = < TEvent extends { currentTarget: { value: any } } >( event$: Observable ): Observable => map( event => event.currentTarget.value )(event$); /** * Maps an Observable of DOM events to an Observable * of the currentTarget checked. * * Example: * * ```typescript * const [onChange, checked$] = useObservableCallback< * boolean, * React.FormEvent * >(pluckCurrentTargetChecked) * ``` * */ export const pluckCurrentTargetChecked = < TEvent extends { currentTarget: { checked: any } } >( event$: Observable ): Observable => map( event => event.currentTarget.checked )(event$); /** * Return an empty Subject * @ignore */ export const getEmptySubject = () => new Subject(); /** * One-time ref init. * @param init A function that returns a value. Will be called only once. * @returns A ref object with the returned value. */ export const useRefFn = (init: () => T) => { const firstRef = useRef(true); const ref = useRef(null); if (firstRef.current) { firstRef.current = false; ref.current = init(); } return ref as MutableRefObject; }; const increment = (n: number): number => (n + 1) | 0; /** * Force re-renders Component. */ export const useForceUpdate = (): (() => void) => { const updateState = useState(0)[1]; return useRef(() => updateState(increment)).current; }; /** * Prevent React warning when using useLayoutEffect on server. */ export const useIsomorphicLayoutEffect = /* @__PURE__ */ (() => /* istanbul ignore next */ typeof window === "undefined" ? useEffect : useLayoutEffect)();