141 lines
4.5 KiB
JavaScript
141 lines
4.5 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.
|
|
*
|
|
* @flow strict-local
|
|
* @format
|
|
*/
|
|
|
|
// flowlint unsafe-getters-setters:off
|
|
|
|
import type ReactNativeElement from '../DOM/Nodes/ReactNativeElement';
|
|
import type {InternalInstanceHandle} from '../Renderer/shims/ReactNativeTypes';
|
|
import type {NativeIntersectionObserverEntry} from './NativeIntersectionObserver';
|
|
|
|
import DOMRectReadOnly from '../DOM/Geometry/DOMRectReadOnly';
|
|
import {getPublicInstanceFromInternalInstanceHandle} from '../DOM/Nodes/ReadOnlyNode';
|
|
|
|
/**
|
|
* The [`IntersectionObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry)
|
|
* interface of the Intersection Observer API describes the intersection between
|
|
* the target element and its root container at a specific moment of transition.
|
|
*
|
|
* An array of `IntersectionObserverEntry` is delivered to
|
|
* `IntersectionObserver` callbacks as the first argument.
|
|
*/
|
|
export default class IntersectionObserverEntry {
|
|
// We lazily compute all the properties from the raw entry provided by the
|
|
// native module, so we avoid unnecessary work.
|
|
_nativeEntry: NativeIntersectionObserverEntry;
|
|
|
|
constructor(nativeEntry: NativeIntersectionObserverEntry) {
|
|
this._nativeEntry = nativeEntry;
|
|
}
|
|
|
|
/**
|
|
* Returns the bounds rectangle of the target element as a `DOMRectReadOnly`.
|
|
* The bounds are computed as described in the documentation for
|
|
* [`Element.getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect).
|
|
*/
|
|
get boundingClientRect(): DOMRectReadOnly {
|
|
const targetRect = this._nativeEntry.targetRect;
|
|
return new DOMRectReadOnly(
|
|
targetRect[0],
|
|
targetRect[1],
|
|
targetRect[2],
|
|
targetRect[3],
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns the ratio of the `intersectionRect` to the `boundingClientRect`.
|
|
*/
|
|
get intersectionRatio(): number {
|
|
const intersectionRect = this.intersectionRect;
|
|
const boundingClientRect = this.boundingClientRect;
|
|
|
|
if (boundingClientRect.width === 0 || boundingClientRect.height === 0) {
|
|
return 0;
|
|
}
|
|
|
|
return (
|
|
(intersectionRect.width * intersectionRect.height) /
|
|
(boundingClientRect.width * boundingClientRect.height)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns a `DOMRectReadOnly` representing the target's visible area.
|
|
*/
|
|
get intersectionRect(): DOMRectReadOnly {
|
|
const intersectionRect = this._nativeEntry.intersectionRect;
|
|
|
|
if (intersectionRect == null) {
|
|
return new DOMRectReadOnly();
|
|
}
|
|
|
|
return new DOMRectReadOnly(
|
|
intersectionRect[0],
|
|
intersectionRect[1],
|
|
intersectionRect[2],
|
|
intersectionRect[3],
|
|
);
|
|
}
|
|
|
|
/**
|
|
* A `Boolean` value which is `true` if the target element intersects with the
|
|
* intersection observer's root.
|
|
* * If this is `true`, then, the `IntersectionObserverEntry` describes a
|
|
* transition into a state of intersection.
|
|
* * If it's `false`, then you know the transition is from intersecting to
|
|
* not-intersecting.
|
|
*/
|
|
get isIntersecting(): boolean {
|
|
return this._nativeEntry.isIntersectingAboveThresholds;
|
|
}
|
|
|
|
/**
|
|
* Returns a `DOMRectReadOnly` for the intersection observer's root.
|
|
*/
|
|
get rootBounds(): DOMRectReadOnly {
|
|
const rootRect = this._nativeEntry.rootRect;
|
|
return new DOMRectReadOnly(
|
|
rootRect[0],
|
|
rootRect[1],
|
|
rootRect[2],
|
|
rootRect[3],
|
|
);
|
|
}
|
|
|
|
/**
|
|
* The `ReactNativeElement` whose intersection with the root changed.
|
|
*/
|
|
get target(): ReactNativeElement {
|
|
const targetInstanceHandle: InternalInstanceHandle =
|
|
// $FlowExpectedError[incompatible-type] native modules don't support using InternalInstanceHandle as a type
|
|
this._nativeEntry.targetInstanceHandle;
|
|
|
|
const targetElement =
|
|
getPublicInstanceFromInternalInstanceHandle(targetInstanceHandle);
|
|
|
|
// $FlowExpectedError[incompatible-cast] we know targetElement is a ReactNativeElement, not just a ReadOnlyNode
|
|
return (targetElement: ReactNativeElement);
|
|
}
|
|
|
|
/**
|
|
* A `DOMHighResTimeStamp` indicating the time at which the intersection was
|
|
* recorded, relative to the `IntersectionObserver`'s time origin.
|
|
*/
|
|
get time(): DOMHighResTimeStamp {
|
|
return this._nativeEntry.time;
|
|
}
|
|
}
|
|
|
|
export function createIntersectionObserverEntry(
|
|
entry: NativeIntersectionObserverEntry,
|
|
): IntersectionObserverEntry {
|
|
return new IntersectionObserverEntry(entry);
|
|
}
|