first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
# 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.
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
file(GLOB react_nativemodule_intersectionobserver_SRC CONFIGURE_DEPENDS *.cpp)
add_library(react_nativemodule_intersectionobserver OBJECT ${react_nativemodule_intersectionobserver_SRC})
target_include_directories(react_nativemodule_intersectionobserver PUBLIC ${REACT_COMMON_DIR})
target_link_libraries(react_nativemodule_intersectionobserver
react_codegen_rncore
react_cxxreact
react_renderer_bridging
react_renderer_core
react_renderer_graphics
react_renderer_observers_intersection
react_renderer_runtimescheduler
react_renderer_uimanager
rrc_view
)
target_compile_reactnative_options(react_nativemodule_intersectionobserver PRIVATE)
target_compile_options(react_nativemodule_intersectionobserver PRIVATE -Wpedantic -Wno-deprecated-declarations)

View File

@@ -0,0 +1,162 @@
/*
* 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.
*/
#include "NativeIntersectionObserver.h"
#include <react/renderer/core/ShadowNode.h>
#include <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
#include <react/renderer/uimanager/UIManagerBinding.h>
#include <react/renderer/uimanager/primitives.h>
#ifdef RN_DISABLE_OSS_PLUGIN_HEADER
#include "Plugins.h"
#endif
std::shared_ptr<facebook::react::TurboModule>
NativeIntersectionObserverModuleProvider(
std::shared_ptr<facebook::react::CallInvoker> jsInvoker) {
return std::make_shared<facebook::react::NativeIntersectionObserver>(
std::move(jsInvoker));
}
namespace facebook::react {
namespace {
jsi::Object tokenFromShadowNodeFamily(
jsi::Runtime& runtime,
ShadowNodeFamily::Shared shadowNodeFamily) {
jsi::Object obj(runtime);
// Need to const_cast since JSI only allows non-const pointees
obj.setNativeState(
runtime,
std::const_pointer_cast<ShadowNodeFamily>(std::move(shadowNodeFamily)));
return obj;
}
ShadowNodeFamily::Shared shadowNodeFamilyFromToken(
jsi::Runtime& runtime,
jsi::Object token) {
return token.getNativeState<ShadowNodeFamily>(runtime);
}
} // namespace
NativeIntersectionObserver::NativeIntersectionObserver(
std::shared_ptr<CallInvoker> jsInvoker)
: NativeIntersectionObserverCxxSpec(std::move(jsInvoker)) {}
jsi::Object NativeIntersectionObserver::observeV2(
jsi::Runtime& runtime,
NativeIntersectionObserverObserveOptions options) {
auto intersectionObserverId = options.intersectionObserverId;
auto shadowNode = options.targetShadowNode;
auto shadowNodeFamily = shadowNode->getFamilyShared();
std::optional<ShadowNodeFamily::Shared> observationRootShadowNodeFamily;
if (options.rootShadowNode.has_value()) {
observationRootShadowNodeFamily =
options.rootShadowNode.value()->getFamilyShared();
}
auto thresholds = options.thresholds;
auto rootThresholds = options.rootThresholds;
auto rootMargin = options.rootMargin;
auto& uiManager = getUIManagerFromRuntime(runtime);
intersectionObserverManager_.observe(
intersectionObserverId,
observationRootShadowNodeFamily,
shadowNodeFamily,
thresholds,
rootThresholds,
rootMargin,
uiManager);
return tokenFromShadowNodeFamily(runtime, shadowNodeFamily);
}
void NativeIntersectionObserver::unobserveV2(
jsi::Runtime& runtime,
IntersectionObserverObserverId intersectionObserverId,
jsi::Object targetToken) {
auto shadowNodeFamily =
shadowNodeFamilyFromToken(runtime, std::move(targetToken));
intersectionObserverManager_.unobserve(
intersectionObserverId, shadowNodeFamily);
}
void NativeIntersectionObserver::connect(
jsi::Runtime& runtime,
AsyncCallback<> notifyIntersectionObserversCallback) {
auto& uiManager = getUIManagerFromRuntime(runtime);
intersectionObserverManager_.connect(
*RuntimeSchedulerBinding::getBinding(runtime)->getRuntimeScheduler(),
uiManager,
std::move(notifyIntersectionObserversCallback));
}
void NativeIntersectionObserver::disconnect(jsi::Runtime& runtime) {
auto& uiManager = getUIManagerFromRuntime(runtime);
intersectionObserverManager_.disconnect(
*RuntimeSchedulerBinding::getBinding(runtime)->getRuntimeScheduler(),
uiManager);
}
std::vector<NativeIntersectionObserverEntry>
NativeIntersectionObserver::takeRecords(jsi::Runtime& runtime) {
auto entries = intersectionObserverManager_.takeRecords();
std::vector<NativeIntersectionObserverEntry> nativeModuleEntries;
nativeModuleEntries.reserve(entries.size());
for (const auto& entry : entries) {
nativeModuleEntries.emplace_back(
convertToNativeModuleEntry(entry, runtime));
}
return nativeModuleEntries;
}
NativeIntersectionObserverEntry
NativeIntersectionObserver::convertToNativeModuleEntry(
const IntersectionObserverEntry& entry,
jsi::Runtime& runtime) {
RectAsTuple targetRect = {
entry.targetRect.origin.x,
entry.targetRect.origin.y,
entry.targetRect.size.width,
entry.targetRect.size.height};
RectAsTuple rootRect = {
entry.rootRect.origin.x,
entry.rootRect.origin.y,
entry.rootRect.size.width,
entry.rootRect.size.height};
RectAsTuple intersectionRect = {
entry.intersectionRect.origin.x,
entry.intersectionRect.origin.y,
entry.intersectionRect.size.width,
entry.intersectionRect.size.height};
NativeIntersectionObserverEntry nativeModuleEntry = {
entry.intersectionObserverId,
(*entry.shadowNodeFamily).getInstanceHandle(runtime),
targetRect,
rootRect,
intersectionRect,
entry.isIntersectingAboveThresholds,
entry.time,
};
return nativeModuleEntry;
}
UIManager& NativeIntersectionObserver::getUIManagerFromRuntime(
jsi::Runtime& runtime) {
return UIManagerBinding::getBinding(runtime)->getUIManager();
}
} // namespace facebook::react

View File

@@ -0,0 +1,89 @@
/*
* 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.
*/
#pragma once
#if __has_include("FBReactNativeSpecJSI.h") // CocoaPod headers on Apple
#include "FBReactNativeSpecJSI.h"
#else
#include <FBReactNativeSpec/FBReactNativeSpecJSI.h>
#endif
#include <react/renderer/bridging/bridging.h>
#include <react/renderer/observers/intersection/IntersectionObserverManager.h>
#include <optional>
#include <tuple>
#include <vector>
namespace facebook::react {
using NativeIntersectionObserverIntersectionObserverId = int32_t;
using RectAsTuple = std::tuple<Float, Float, Float, Float>;
using NativeIntersectionObserverObserveOptions = NativeIntersectionObserverNativeIntersectionObserverObserveOptions<
// intersectionObserverId
NativeIntersectionObserverIntersectionObserverId,
// rootShadowNode
std::optional<std::shared_ptr<const ShadowNode>>,
// targetShadowNode
std::shared_ptr<const ShadowNode>,
// thresholds
std::vector<Float>,
// rootThresholds
std::optional<std::vector<Float>>,
// rootMargin
std::optional<std::string>>;
template <>
struct Bridging<NativeIntersectionObserverObserveOptions>
: NativeIntersectionObserverNativeIntersectionObserverObserveOptionsBridging<
NativeIntersectionObserverObserveOptions> {};
using NativeIntersectionObserverEntry = NativeIntersectionObserverNativeIntersectionObserverEntry<
// intersectionObserverId
NativeIntersectionObserverIntersectionObserverId,
// targetInstanceHandle
jsi::Value,
// targetRect
RectAsTuple,
// rootRect
RectAsTuple,
// intersectionRect
RectAsTuple,
// isIntersectingAboveThresholds
bool,
// time
HighResTimeStamp>;
template <>
struct Bridging<NativeIntersectionObserverEntry>
: NativeIntersectionObserverNativeIntersectionObserverEntryBridging<NativeIntersectionObserverEntry> {};
class NativeIntersectionObserver : public NativeIntersectionObserverCxxSpec<NativeIntersectionObserver> {
public:
NativeIntersectionObserver(std::shared_ptr<CallInvoker> jsInvoker);
jsi::Object observeV2(jsi::Runtime &runtime, NativeIntersectionObserverObserveOptions options);
void
unobserveV2(jsi::Runtime &runtime, IntersectionObserverObserverId intersectionObserverId, jsi::Object targetToken);
void connect(jsi::Runtime &runtime, AsyncCallback<> notifyIntersectionObserversCallback);
void disconnect(jsi::Runtime &runtime);
std::vector<NativeIntersectionObserverEntry> takeRecords(jsi::Runtime &runtime);
private:
IntersectionObserverManager intersectionObserverManager_{};
static UIManager &getUIManagerFromRuntime(jsi::Runtime &runtime);
static NativeIntersectionObserverEntry convertToNativeModuleEntry(
const IntersectionObserverEntry &entry,
jsi::Runtime &runtime);
};
} // namespace facebook::react

View File

@@ -0,0 +1,66 @@
# 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.
require "json"
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "..", "package.json")))
version = package['version']
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which we're presumably in.
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
else
source[:tag] = "v#{version}"
end
header_search_paths = [
"\"$(PODS_ROOT)/Headers/Private/Yoga\"",
]
if ENV['USE_FRAMEWORKS']
header_search_paths << "\"$(PODS_TARGET_SRCROOT)/../../..\"" # this is needed to allow the module access its own files
end
Pod::Spec.new do |s|
s.name = "React-intersectionobservernativemodule"
s.version = version
s.summary = "React Native intersection observer native module"
s.homepage = "https://reactnative.dev/"
s.license = package["license"]
s.author = "Meta Platforms, Inc. and its affiliates"
s.platforms = min_supported_versions
s.source = source
s.source_files = podspec_sources("*.{cpp,h}", "*.h")
s.header_dir = "react/nativemodule/intersectionobserver"
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
"OTHER_CFLAGS" => "$(inherited)",
"DEFINES_MODULE" => "YES" }
if ENV['USE_FRAMEWORKS']
s.module_name = "intersectionobservernativemodule"
s.header_mappings_dir = "../.."
end
s.dependency "Yoga"
s.dependency "React-jsi"
s.dependency "React-jsiexecutor"
s.dependency "React-cxxreact"
depend_on_js_engine(s)
add_rn_third_party_dependencies(s)
add_rncore_dependency(s)
s.dependency "ReactCommon/turbomodule/core"
s.dependency "React-Fabric"
s.dependency "React-Fabric/bridging"
s.dependency "React-runtimescheduler"
add_dependency(s, "React-RCTFBReactNativeSpec")
add_dependency(s, "React-runtimeexecutor", :additional_framework_paths => ["platform/ios"])
add_dependency(s, "React-graphics", :additional_framework_paths => ["react/renderer/graphics/platform/ios"])
end