Mirror: React hooks for accessible, common web interactions. UI super powers without the UI.

Add useForwardedRef utility

Changed files
+35
src
+2
src/index.ts
···
+
export * from './types';
export * from './useModalFocus';
export * from './useDialogFocus';
export * from './useMenuFocus';
export * from './useDismissable';
export * from './useScrollRestoration';
export * from './useStyleTransition';
+
export * from './useForwardedRef';
+33
src/useForwardedRef.ts
···
+
import { useRef, ForwardedRef } from 'react';
+
import { Ref } from './types';
+
+
type RefWithState<T extends HTMLElement> = Ref<T> & {
+
_forwarded?: ForwardedRef<T>;
+
_current?: T | null;
+
};
+
+
export function useForwardedRef<T extends HTMLElement>(
+
forwarded: ForwardedRef<T>
+
): Ref<T> {
+
const ref: RefWithState<T> = useRef<T>(null);
+
if (ref._forwarded !== forwarded) {
+
ref._forwarded = forwarded;
+
Object.defineProperty(ref, 'current', {
+
enumerable: true,
+
configurable: true,
+
get() {
+
return this._current || null;
+
},
+
set(value: T | null) {
+
this._current = value;
+
if (typeof this._forwarded === 'function') {
+
this._forwarded(value);
+
} else if (forwarded) {
+
this._forwarded.current = value;
+
}
+
},
+
});
+
}
+
+
return ref;
+
}