UNPKG

@maskito/react

Version:

The React-specific Maskito's library

67 lines (62 loc) 2.22 kB
'use strict'; var core = require('@maskito/core'); var react = require('react'); const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? react.useLayoutEffect : react.useEffect; function isThenable(x) { return x && typeof x === 'object' && 'then' in x; } /** * Hook for convenient use of Maskito in React * @description For controlled inputs use `onInput` event * @param options options used for creating Maskito * @param elementPredicate function that can help find nested Input or TextArea * @returns ref callback to pass it in React Element * @example * // To avoid unnecessary hook runs with Maskito recreation pass named variables * // good example ✅ * useMaskito({ options: maskitoOptions, elementPredicate: maskitoPredicate }) * * // bad example ❌ * useMaskito({ options: { mask: /^.*$/ }, elementPredicate: () => e.querySelector('input') }) */ const useMaskito = ({ options = null, elementPredicate = core.MASKITO_DEFAULT_ELEMENT_PREDICATE } = {}) => { const [hostElement, setHostElement] = react.useState(null); const [element, setElement] = react.useState(null); const onRefChange = react.useCallback(node => { setHostElement(node); }, []); const latestPredicateRef = react.useRef(elementPredicate); const latestOptionsRef = react.useRef(options); latestPredicateRef.current = elementPredicate; latestOptionsRef.current = options; useIsomorphicLayoutEffect(() => { if (!hostElement) { return; } const elementOrPromise = elementPredicate(hostElement); if (isThenable(elementOrPromise)) { void elementOrPromise.then(el => { if (latestPredicateRef.current === elementPredicate && latestOptionsRef.current === options) { setElement(el); } }); } else { setElement(elementOrPromise); } }, [hostElement, elementPredicate, latestPredicateRef, options, latestOptionsRef]); useIsomorphicLayoutEffect(() => { if (!element || !options) { return; } const maskedElement = new core.Maskito(element, options); return () => { maskedElement.destroy(); setElement(null); }; }, [options, element]); return onRefChange; }; exports.useMaskito = useMaskito;