UNPKG

react-native

Version:

A framework for building native apps using React

580 lines (499 loc) • 18.9 kB
/** * 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. * * @flow strict-local * @format */ import type {RootTag} from '../../../../../../Libraries/ReactNative/RootTag'; import type {Node as ShadowNode} from '../../../../../../Libraries/Renderer/shims/ReactNativeTypes'; import type {TurboModule} from '../../../../../../Libraries/TurboModule/RCTExport'; import type {InstanceHandle} from '../internals/NodeInternals'; import * as TurboModuleRegistry from '../../../../../../Libraries/TurboModule/TurboModuleRegistry'; import nullthrows from 'nullthrows'; export opaque type NativeElementReference = ShadowNode; export opaque type NativeTextReference = ShadowNode; export type NativeNodeReference = | NativeElementReference | NativeTextReference | RootTag; export type MeasureInWindowOnSuccessCallback = ( x: number, y: number, width: number, height: number, ) => void; export type MeasureOnSuccessCallback = ( x: number, y: number, width: number, height: number, pageX: number, pageY: number, ) => void; export type MeasureLayoutOnSuccessCallback = ( left: number, top: number, width: number, height: number, ) => void; export interface Spec extends TurboModule { /* * Methods from the `Node` interface (for `ReadOnlyNode`). */ +compareDocumentPosition: ( nativeNodeReference: mixed /* NativeNodeReference */, otherNativeNodeReference: mixed /* NativeNodeReference */, ) => number; +getChildNodes: ( nativeNodeReference: mixed /* NativeNodeReference */, ) => $ReadOnlyArray<mixed> /* $ReadOnlyArray<InstanceHandle> */; +getParentNode: ( nativeNodeReference: mixed /* NativeNodeReference */, ) => mixed /* ?InstanceHandle */; +isConnected: ( nativeNodeReference: mixed /* NativeNodeReference */, ) => boolean; /* * Methods from the `Element` interface (for `ReactNativeElement`). */ +getBorderWidth: ( nativeElementReference: mixed /* NativeElementReference */, ) => $ReadOnlyArray<number> /* [topWidth: number, rightWidth: number, bottomWidth: number, leftWidth: number] */; +getBoundingClientRect: ( nativeElementReference: mixed /* NativeElementReference */, includeTransform: boolean, ) => $ReadOnlyArray<number> /* [x: number, y: number, width: number, height: number] */; +getInnerSize: ( nativeElementReference: mixed /* NativeElementReference */, ) => $ReadOnlyArray<number> /* [width: number, height: number] */; +getScrollPosition: ( nativeElementReference: mixed /* NativeElementReference */, ) => $ReadOnlyArray<number> /* [scrollLeft: number, scrollTop: number] */; +getScrollSize: ( nativeElementReference: mixed /* NativeElementReference */, ) => $ReadOnlyArray<number> /* [scrollWidth: number, scrollHeight: number] */; +getTagName: ( nativeElementReference: mixed /* NativeElementReference */, ) => string; +getTextContent: ( nativeElementReference: mixed /* NativeElementReference */, ) => string; +hasPointerCapture: ( nativeElementReference: mixed /* NativeElementReference */, pointerId: number, ) => boolean; +releasePointerCapture: ( nativeElementReference: mixed /* NativeElementReference */, pointerId: number, ) => void; +setPointerCapture: ( nativeElementReference: mixed /* NativeElementReference */, pointerId: number, ) => void; /* * Methods from the `HTMLElement` interface (for `ReactNativeElement`). */ +getOffset: ( nativeElementReference: mixed /* NativeElementReference */, ) => $ReadOnlyArray<mixed> /* [offsetParent: ?InstanceHandle, top: number, left: number] */; /* * Special methods to handle the root node. */ +linkRootNode?: ( rootTag: number /* RootTag */, instanceHandle: mixed /* InstanceHandle */, ) => mixed /* ?NativeElementReference */; /** * Legacy layout APIs (for `ReactNativeElement`). */ +measure: ( nativeElementReference: mixed, callback: MeasureOnSuccessCallback, ) => void; +measureInWindow: ( nativeElementReference: mixed, callback: MeasureInWindowOnSuccessCallback, ) => void; +measureLayout: ( nativeElementReference: mixed, relativeNode: mixed, onFail: () => void, onSuccess: MeasureLayoutOnSuccessCallback, ) => void; } const RawNativeDOM = (TurboModuleRegistry.get<Spec>('NativeDOMCxx'): ?Spec); // This is the actual interface of this module, but the native module codegen // isn't expressive enough yet. export interface RefinedSpec { /* * Methods from the `Node` interface (for `ReadOnlyNode`). */ /** * This is a React Native implementation of `Node.prototype.compareDocumentPosition` * (see https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition). * * It uses the version of the shadow nodes that are present in the current * revision of the shadow tree (if any). If any of the nodes is not present, * it just indicates they are disconnected. */ +compareDocumentPosition: ( nativeNodeReference: NativeNodeReference, otherNativeNodeReference: NativeNodeReference, ) => number; /** * This is a React Native implementation of `Node.prototype.childNodes` * (see https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes). * * If a version of the given shadow node is present in the current revision * of an active shadow tree, it returns an array of instance handles of its * children. Otherwise, it returns an empty array. */ +getChildNodes: ( nativeNodeReference: NativeNodeReference, ) => $ReadOnlyArray<InstanceHandle>; /** * This is a React Native implementation of `Node.prototype.parentNode` * (see https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode). * * If a version of the given shadow node is present in the current revision of * an active shadow tree, it returns the instance handle of its parent. * Otherwise, it returns `null`. */ +getParentNode: (nativeNodeReference: NativeNodeReference) => ?InstanceHandle; /** * This is a React Native implementation of `Node.prototype.isConnected` * (see https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected). * * Indicates whether a version of the given shadow node is present in the * current revision of an active shadow tree. */ +isConnected: (nativeNodeReference: NativeNodeReference) => boolean; /* * Methods from the `Element` interface (for `ReactNativeElement`). */ /** * This is a method to access the border size of a shadow node, to implement * these methods: * - `Element.prototype.clientLeft`: see https://developer.mozilla.org/en-US/docs/Web/API/Element/clientLeft. * - `Element.prototype.clientTop`: see https://developer.mozilla.org/en-US/docs/Web/API/Element/clientTop. * * It uses the version of the shadow node that is present in the current * revision of the shadow tree. If the node is not present, it is not * displayed (because any of its ancestors or itself have 'display: none'), or * it has an inline display, it returns `undefined`. Otherwise, it returns its * border size. */ +getBorderWidth: ( nativeElementReference: NativeElementReference, ) => $ReadOnly< [ /* topWidth: */ number, /* rightWidth: */ number, /* bottomWidth: */ number, /* leftWidth: */ number, ], >; /** * This is a React Native implementation of `Element.prototype.getBoundingClientRect` * (see https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect). * * This is similar to `measureInWindow`, except it's explicitly synchronous * (returns the result instead of passing it to a callback). * * It allows indicating whether to include transforms so it can also be used * to implement methods like [`offsetWidth`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth) * and [`offsetHeight`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight). */ +getBoundingClientRect: ( nativeElementReference: NativeElementReference, includeTransform: boolean, ) => $ReadOnly< [ /* x: */ number, /* y: */ number, /* width: */ number, /* height: */ number, ], >; /** * This is a method to access the inner size of a shadow node, to implement * these methods: * - `Element.prototype.clientWidth`: see https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth. * - `Element.prototype.clientHeight`: see https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight. * * It uses the version of the shadow node that is present in the current * revision of the shadow tree. If the node is not present, it is not * displayed (because any of its ancestors or itself have 'display: none'), or * it has an inline display, it returns `undefined`. Otherwise, it returns its * inner size. */ +getInnerSize: ( nativeElementReference: NativeElementReference, ) => $ReadOnly<[/* width: */ number, /* height: */ number]>; /** * This is a method to access scroll information for a shadow node, to * implement these methods: * - `Element.prototype.scrollLeft`: see https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft. * - `Element.prototype.scrollTop`: see https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop. * * It uses the version of the shadow node that is present in the current * revision of the shadow tree. If the node is not present or is not displayed * (because any of its ancestors or itself have 'display: none'), it returns * `undefined`. Otherwise, it returns the scroll position. */ +getScrollPosition: ( nativeElementReference: NativeElementReference, ) => $ReadOnly<[/* scrollLeft: */ number, /* scrollTop: */ number]>; /** * * This is a method to access the scroll information of a shadow node, to * implement these methods: * - `Element.prototype.scrollWidth`: see https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollWidth. * - `Element.prototype.scrollHeight`: see https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight. * * It uses the version of the shadow node that is present in the current * revision of the shadow tree. If the node is not present or is not displayed * (because any of its ancestors or itself have 'display: none'), it returns * `undefined`. Otherwise, it returns the scroll size. */ +getScrollSize: ( nativeElementReference: NativeElementReference, ) => $ReadOnly<[/* scrollWidth: */ number, /* scrollHeight: */ number]>; /** * This is a method to access the normalized tag name of a shadow node, to * implement `Element.prototype.tagName` (see https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName). */ +getTagName: (nativeElementReference: NativeElementReference) => string; /** * This is a React Native implementation of `Element.prototype.textContent` * (see https://developer.mozilla.org/en-US/docs/Web/API/Element/textContent). * * It uses the version of the shadow node that is present in the current * revision of the shadow tree. * If the version is present, is traverses all its children in DFS and * concatenates all the text contents. Otherwise, it returns an empty string. * * This is also used to access the text content of text nodes, which does not * need any traversal. */ +getTextContent: (nativeNodeReference: NativeNodeReference) => string; +hasPointerCapture: ( nativeElementReference: NativeElementReference, pointerId: number, ) => boolean; +releasePointerCapture: ( nativeElementReference: NativeElementReference, pointerId: number, ) => void; +setPointerCapture: ( nativeElementReference: NativeElementReference, pointerId: number, ) => void; /** * This is a method to access the offset information for a shadow node, to * implement these methods: * - `HTMLElement.prototype.offsetParent`: see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent. * - `HTMLElement.prototype.offsetTop`: see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop. * - `HTMLElement.prototype.offsetLeft`: see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetLeft. * * It uses the version of the shadow node that is present in the current * revision of the shadow tree. If the node is not present or is not * displayed (because any of its ancestors or itself have 'display: none'), * it returns `undefined`. Otherwise, it returns its parent (as all nodes in * React Native are currently "positioned") and its offset relative to its * parent. */ +getOffset: ( nativeElementReference: NativeElementReference, ) => $ReadOnly< [ /* offsetParent: */ ?InstanceHandle, /* top: */ number, /* left: */ number, ], >; /* * Special methods to handle the root node. */ /** * In React Native, surfaces that represent trees (similar to a `Document` on * Web) are created in native first, and then populated from JavaScript. * * Because React does not create this special node, we need a way to link * the JavaScript instance with that node, which is what this method allows. * * It also allows the implementation of `Node.prototype.ownerDocument` and * `Node.prototype.getRootNode` * (see https://developer.mozilla.org/en-US/docs/Web/API/Node/ownerDocument and * https://developer.mozilla.org/en-US/docs/Web/API/Node/getRootNode). * * Returns a shadow node representing the root node if it is still mounted. */ +linkRootNode: ( rootTag: RootTag, instanceHandle: InstanceHandle, ) => ?NativeElementReference; /** * Legacy layout APIs */ +measure: ( nativeElementReference: NativeElementReference, callback: MeasureOnSuccessCallback, ) => void; +measureInWindow: ( nativeElementReference: NativeElementReference, callback: MeasureInWindowOnSuccessCallback, ) => void; +measureLayout: ( nativeElementReference: NativeElementReference, relativeNode: NativeElementReference, onFail: () => void, onSuccess: MeasureLayoutOnSuccessCallback, ) => void; } const NativeDOM: RefinedSpec = { /* * Methods from the `Node` interface (for `ReadOnlyNode`). */ compareDocumentPosition(nativeNodeReference, otherNativeNodeReference) { return nullthrows(RawNativeDOM).compareDocumentPosition( nativeNodeReference, otherNativeNodeReference, ); }, getChildNodes(nativeNodeReference) { // $FlowExpectedError[incompatible-cast] return (nullthrows(RawNativeDOM).getChildNodes( nativeNodeReference, ): $ReadOnlyArray<InstanceHandle>); }, getParentNode(nativeNodeReference) { // $FlowExpectedError[incompatible-cast] return (nullthrows(RawNativeDOM).getParentNode( nativeNodeReference, ): ?InstanceHandle); }, isConnected(nativeNodeReference) { return nullthrows(RawNativeDOM).isConnected(nativeNodeReference); }, /* * Methods from the `Element` interface (for `ReactNativeElement`). */ getBorderWidth(nativeNodeReference) { // $FlowExpectedError[incompatible-cast] return (nullthrows(RawNativeDOM).getBorderWidth( nativeNodeReference, ): $ReadOnly< [ /* topWidth: */ number, /* rightWidth: */ number, /* bottomWidth: */ number, /* leftWidth: */ number, ], >); }, getBoundingClientRect(nativeNodeReference, includeTransform: boolean) { // $FlowExpectedError[incompatible-cast] return (nullthrows(RawNativeDOM).getBoundingClientRect( nativeNodeReference, includeTransform, ): $ReadOnly< [ /* x: */ number, /* y: */ number, /* width: */ number, /* height: */ number, ], >); }, getInnerSize(nativeNodeReference) { // $FlowExpectedError[incompatible-cast] return (nullthrows(RawNativeDOM).getInnerSize( nativeNodeReference, ): $ReadOnly<[/* width: */ number, /* height: */ number]>); }, getScrollPosition(nativeNodeReference) { // $FlowExpectedError[incompatible-cast] return (nullthrows(RawNativeDOM).getScrollPosition( nativeNodeReference, ): $ReadOnly<[/* scrollLeft: */ number, /* scrollTop: */ number]>); }, getScrollSize(nativeNodeReference) { // $FlowExpectedError[incompatible-cast] return (nullthrows(RawNativeDOM).getScrollSize( nativeNodeReference, ): $ReadOnly<[/* scrollWidth: */ number, /* scrollHeight: */ number]>); }, getTagName(nativeNodeReference) { return nullthrows(RawNativeDOM).getTagName(nativeNodeReference); }, getTextContent(nativeNodeReference) { return nullthrows(RawNativeDOM).getTextContent(nativeNodeReference); }, hasPointerCapture(nativeNodeReference, pointerId) { return nullthrows(RawNativeDOM).hasPointerCapture( nativeNodeReference, pointerId, ); }, releasePointerCapture(nativeNodeReference, pointerId) { return nullthrows(RawNativeDOM).releasePointerCapture( nativeNodeReference, pointerId, ); }, setPointerCapture(nativeNodeReference, pointerId) { return nullthrows(RawNativeDOM).setPointerCapture( nativeNodeReference, pointerId, ); }, /* * Methods from the `HTMLElement` interface (for `ReactNativeElement`). */ getOffset(nativeNodeReference) { // $FlowExpectedError[incompatible-cast] return (nullthrows(RawNativeDOM).getOffset(nativeNodeReference): $ReadOnly< [ /* offsetParent: */ ?InstanceHandle, /* top: */ number, /* left: */ number, ], >); }, /* * Special methods to handle the root node. */ linkRootNode(rootTag, instanceHandle) { // $FlowExpectedError[incompatible-cast] return (nullthrows(RawNativeDOM?.linkRootNode)( // $FlowExpectedError[incompatible-call] rootTag, instanceHandle, ): ?NativeElementReference); }, /** * Legacy layout APIs */ measure(nativeNodeReference, callback) { return nullthrows(RawNativeDOM).measure(nativeNodeReference, callback); }, measureInWindow(nativeNodeReference, callback) { return nullthrows(RawNativeDOM).measureInWindow( nativeNodeReference, callback, ); }, measureLayout(nativeNodeReference, relativeNode, onFail, onSuccess) { return nullthrows(RawNativeDOM).measureLayout( nativeNodeReference, relativeNode, onFail, onSuccess, ); }, }; export default NativeDOM;