@hypothesis/frontend-shared
Version:
Shared components, styles and utilities for Hypothesis projects
79 lines (76 loc) • 2.68 kB
JavaScript
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
import { useRef } from 'preact/hooks';
/**
* Object ref which synchronizes its value to another ref.
*/
class SyncedRef {
/**
* @param [target] - Initial target for this ref to synchronize to.
* This is not called/set until the {@link current} property of the
* SyncedRef is set. This makes the target behave close to how it would
* if used in place of the SyncedRef.
*/
constructor(target) {
_defineProperty(this, "_target", void 0);
_defineProperty(this, "_value", void 0);
this._target = target;
this._value = null;
}
get current() {
return this._value;
}
set current(value) {
this._value = value;
this._updateTarget();
}
get target() {
return this._target;
}
set target(target) {
if (target === this._target) {
return;
}
this._target = target;
// If the target changes after the initial render, we currently synchronize
// the value immediately. This is different than what happens if the target
// were passed to an element directly, as it would be updated only after the
// render.
this._updateTarget();
}
_updateTarget() {
const value = this._value;
if (typeof this._target === 'function') {
this._target(value);
} else if (this._target) {
this._target.current = value;
}
}
}
/**
* Return an object ref which synchronizes its value to another "target" ref.
*
* This is useful when a component needs an object ref for an element for
* internal use, but also wants to allow the caller to get a ref for the same
* element.
*
* The target ref can be either a callback or an object.
*
* @example
* function Widget({ elementRef }) {
* const ref = useSyncedRef(elementRef);
*
* useEffect(() => {
* ref.current.focus();
* }, []);
*
* return <input ref={ref}>...</input>;
* }
*/
export function useSyncedRef(targetRef) {
const container = useRef(new SyncedRef(targetRef));
container.current.target = targetRef;
return container.current;
}
//# sourceMappingURL=use-synced-ref.js.map