116 lines
3.3 KiB
JavaScript
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:
|
|
}
|
|
}
|
|
};
|
|
}
|
|
};
|
|
} |