151 lines
4.1 KiB
JavaScript
151 lines
4.1 KiB
JavaScript
|
/**
|
||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||
|
*
|
||
|
* This source code is licensed under the MIT license found in the
|
||
|
* LICENSE file in the root directory of this source tree.
|
||
|
*
|
||
|
* @format
|
||
|
* @flow strict-local
|
||
|
*/
|
||
|
|
||
|
import type {
|
||
|
HostInstance,
|
||
|
INativeMethods,
|
||
|
InternalInstanceHandle,
|
||
|
MeasureInWindowOnSuccessCallback,
|
||
|
MeasureLayoutOnSuccessCallback,
|
||
|
MeasureOnSuccessCallback,
|
||
|
ViewConfig,
|
||
|
} from '../../Renderer/shims/ReactNativeTypes';
|
||
|
|
||
|
import TextInputState from '../../Components/TextInput/TextInputState';
|
||
|
import {getNodeFromInternalInstanceHandle} from '../../ReactNative/RendererProxy';
|
||
|
import {getFabricUIManager} from '../FabricUIManager';
|
||
|
import {create} from './ReactNativeAttributePayload';
|
||
|
import warnForStyleProps from './warnForStyleProps';
|
||
|
import nullthrows from 'nullthrows';
|
||
|
|
||
|
const {
|
||
|
measure: fabricMeasure,
|
||
|
measureInWindow: fabricMeasureInWindow,
|
||
|
measureLayout: fabricMeasureLayout,
|
||
|
getBoundingClientRect: fabricGetBoundingClientRect,
|
||
|
setNativeProps,
|
||
|
} = nullthrows(getFabricUIManager());
|
||
|
|
||
|
const noop = () => {};
|
||
|
|
||
|
/**
|
||
|
* This is used for refs on host components.
|
||
|
*/
|
||
|
export default class ReactFabricHostComponent implements INativeMethods {
|
||
|
// These need to be accessible from `ReactFabricPublicInstanceUtils`.
|
||
|
__nativeTag: number;
|
||
|
__internalInstanceHandle: InternalInstanceHandle;
|
||
|
|
||
|
_viewConfig: ViewConfig;
|
||
|
|
||
|
constructor(
|
||
|
tag: number,
|
||
|
viewConfig: ViewConfig,
|
||
|
internalInstanceHandle: InternalInstanceHandle,
|
||
|
) {
|
||
|
this.__nativeTag = tag;
|
||
|
this._viewConfig = viewConfig;
|
||
|
this.__internalInstanceHandle = internalInstanceHandle;
|
||
|
}
|
||
|
|
||
|
blur() {
|
||
|
// $FlowFixMe[incompatible-exact] Migrate all usages of `NativeMethods` to an interface to fix this.
|
||
|
TextInputState.blurTextInput(this);
|
||
|
}
|
||
|
|
||
|
focus() {
|
||
|
// $FlowFixMe[incompatible-exact] Migrate all usages of `NativeMethods` to an interface to fix this.
|
||
|
TextInputState.focusTextInput(this);
|
||
|
}
|
||
|
|
||
|
measure(callback: MeasureOnSuccessCallback) {
|
||
|
const node = getNodeFromInternalInstanceHandle(
|
||
|
this.__internalInstanceHandle,
|
||
|
);
|
||
|
if (node != null) {
|
||
|
fabricMeasure(node, callback);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
measureInWindow(callback: MeasureInWindowOnSuccessCallback) {
|
||
|
const node = getNodeFromInternalInstanceHandle(
|
||
|
this.__internalInstanceHandle,
|
||
|
);
|
||
|
if (node != null) {
|
||
|
fabricMeasureInWindow(node, callback);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
measureLayout(
|
||
|
relativeToNativeNode: number | HostInstance,
|
||
|
onSuccess: MeasureLayoutOnSuccessCallback,
|
||
|
onFail?: () => void /* currently unused */,
|
||
|
) {
|
||
|
if (
|
||
|
typeof relativeToNativeNode === 'number' ||
|
||
|
!(relativeToNativeNode instanceof ReactFabricHostComponent)
|
||
|
) {
|
||
|
if (__DEV__) {
|
||
|
console.error(
|
||
|
'Warning: ref.measureLayout must be called with a ref to a native component.',
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const toStateNode = getNodeFromInternalInstanceHandle(
|
||
|
this.__internalInstanceHandle,
|
||
|
);
|
||
|
const fromStateNode = getNodeFromInternalInstanceHandle(
|
||
|
relativeToNativeNode.__internalInstanceHandle,
|
||
|
);
|
||
|
|
||
|
if (toStateNode != null && fromStateNode != null) {
|
||
|
fabricMeasureLayout(
|
||
|
toStateNode,
|
||
|
fromStateNode,
|
||
|
onFail != null ? onFail : noop,
|
||
|
onSuccess != null ? onSuccess : noop,
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unstable_getBoundingClientRect(): DOMRect {
|
||
|
const node = getNodeFromInternalInstanceHandle(
|
||
|
this.__internalInstanceHandle,
|
||
|
);
|
||
|
if (node != null) {
|
||
|
const rect = fabricGetBoundingClientRect(node, true);
|
||
|
|
||
|
if (rect) {
|
||
|
return new DOMRect(rect[0], rect[1], rect[2], rect[3]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Empty rect if any of the above failed
|
||
|
return new DOMRect(0, 0, 0, 0);
|
||
|
}
|
||
|
|
||
|
setNativeProps(nativeProps: {...}): void {
|
||
|
if (__DEV__) {
|
||
|
warnForStyleProps(nativeProps, this._viewConfig.validAttributes);
|
||
|
}
|
||
|
const updatePayload = create(nativeProps, this._viewConfig.validAttributes);
|
||
|
|
||
|
const node = getNodeFromInternalInstanceHandle(
|
||
|
this.__internalInstanceHandle,
|
||
|
);
|
||
|
if (node != null && updatePayload != null) {
|
||
|
setNativeProps(node, updatePayload);
|
||
|
}
|
||
|
}
|
||
|
}
|