Files
2026-08-07 21:39:30 +02:00

116 lines
3.3 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useMergedRefs = useMergedRefs;
exports.useMergedRefsN = useMergedRefsN;
var _useRefWithInit = require("./useRefWithInit");
/**
* Merges refs into a single memoized callback ref or `null`.
* This makes sure multiple refs are updated together and have the same value.
*
* This function accepts up to four refs. If you need to merge more, or have an unspecified number of refs to merge,
* use `useMergedRefsN` instead.
*/
function useMergedRefs(a, b, c, d) {
const forkRef = (0, _useRefWithInit.useRefWithInit)(createForkRef).current;
if (didChange(forkRef, a, b, c, d)) {
update(forkRef, [a, b, c, d]);
}
return forkRef.callback;
}
/**
* Merges an array of refs into a single memoized callback ref or `null`.
*
* If you need to merge a fixed number (up to four) of refs, use `useMergedRefs` instead for better performance.
*/
function useMergedRefsN(refs) {
const forkRef = (0, _useRefWithInit.useRefWithInit)(createForkRef).current;
if (didChangeN(forkRef, refs)) {
update(forkRef, refs);
}
return forkRef.callback;
}
function createForkRef() {
return {
callback: null,
cleanup: null,
refs: []
};
}
function didChange(forkRef, a, b, c, d) {
// prettier-ignore
return forkRef.refs[0] !== a || forkRef.refs[1] !== b || forkRef.refs[2] !== c || forkRef.refs[3] !== d;
}
function didChangeN(forkRef, newRefs) {
return forkRef.refs.length !== newRefs.length || forkRef.refs.some((ref, index) => ref !== newRefs[index]);
}
function update(forkRef, refs) {
forkRef.refs = refs;
if (refs.every(ref => ref == null)) {
forkRef.callback = null;
return;
}
forkRef.callback = instance => {
if (forkRef.cleanup) {
forkRef.cleanup();
forkRef.cleanup = null;
}
if (instance != null) {
const cleanupCallbacks = Array(refs.length).fill(null);
for (let i = 0; i < refs.length; i += 1) {
const ref = refs[i];
if (ref == null) {
continue;
}
switch (typeof ref) {
case 'function':
{
const refCleanup = ref(instance);
if (typeof refCleanup === 'function') {
cleanupCallbacks[i] = refCleanup;
}
break;
}
case 'object':
{
ref.current = instance;
break;
}
default:
}
}
forkRef.cleanup = () => {
for (let i = 0; i < refs.length; i += 1) {
const ref = refs[i];
if (ref == null) {
continue;
}
switch (typeof ref) {
case 'function':
{
const cleanupCallback = cleanupCallbacks[i];
if (typeof cleanupCallback === 'function') {
cleanupCallback();
} else {
// Legacy ref with no attach-time cleanup: detach by calling it with `null`.
// It returns nothing; React 19 cleanups are handled in the branch above.
void ref(null);
}
break;
}
case 'object':
{
ref.current = null;
break;
}
default:
}
}
};
}
};
}