import { isNonNullable, isNullable } from './utils.js';
var CALLBACK_AS_KEY = { callbackAsKey: true };
var cache = new WeakMap();
/**
 * Позволяет объединить несколько параметров ref в один вызов, в котором во все переданные параметры просетится ref.
 *
 * Кеширует результат возвращаемой функции, так что при одинаковых входных параметрах React-у будет возвращена одинаковая функция.
 * Это позволит не вызывать лишние commitAttachRef и commitDetachRef и не ловить сайдэффекты связанные со значением ref в моменте
 *
 * Не прокидывай в параметрах стрелочные функции, так результат не будет закеширован.
 *
 * @returns function that passed refs: (...refs) =>
 *
 * @example
 * const SomeComponent = forwardRef((props, ref) => {
 *  const localRef = useRef();
 *  return <div ref={mergeRefs(localRef, ref)} />;
 * });
 */
export function mergeRefs() {
    var refs = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        refs[_i] = arguments[_i];
    }
    var cacheLevel = getLeafRefInCache.apply(void 0, refs);
    var cachedCallback = cacheLevel.get(CALLBACK_AS_KEY);
    if (cachedCallback && typeof cachedCallback === 'function') {
        return cachedCallback;
    }
    var newRefCallback = createRefCallback(refs);
    cacheLevel.set(CALLBACK_AS_KEY, newRefCallback);
    return newRefCallback;
}
function createRefCallback(refs) {
    function applyRef(value) {
        refs.forEach(function (ref) {
            if (typeof ref === 'function') {
                return ref(value);
            }
            else if (isNonNullable(ref)) {
                return (ref.current = value);
            }
        });
    }
    return applyRef;
}
function getLeafRefInCache() {
    var refs = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        refs[_i] = arguments[_i];
    }
    var cacheLevel = cache;
    for (var _a = 0, refs_1 = refs; _a < refs_1.length; _a++) {
        var ref = refs_1[_a];
        if (isNullable(ref)) {
            continue;
        }
        var child = cacheLevel.get(ref);
        if (child && typeof child !== 'function') {
            cacheLevel = child;
        }
        else {
            var leaf = new WeakMap();
            cacheLevel.set(ref, leaf);
            cacheLevel = leaf;
        }
    }
    return cacheLevel;
}
//# sourceMappingURL=mergeRefs.js.map