diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm index c27f816e14e1..9c59453b4c7f 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm @@ -256,7 +256,16 @@ - (void)boundsDidChange:(CGRect)newBounds } if (_state != nullptr) { - auto newState = ModalHostViewState{RCTSizeFromCGSize(newBounds.size)}; + CGPoint viewportOffset = CGPointZero; + UIView *modalView = _viewController.view; + if (modalView && modalView.window) { + CGRect frameInWindow = [modalView convertRect:modalView.bounds toView:nil]; + viewportOffset = frameInWindow.origin; + } + auto newState = ModalHostViewState{ + RCTSizeFromCGSize(newBounds.size), + facebook::react::Point{(Float)viewportOffset.x, (Float)viewportOffset.y} + }; _state->updateState(std::move(newState)); } } diff --git a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.cpp index 3598549813af..bbdfe2ac73d0 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.cpp @@ -14,4 +14,9 @@ namespace facebook::react { extern const char ModalHostViewComponentName[] = "ModalHostView"; +Transform ModalHostViewShadowNode::getTransform() const { + auto viewportOffset = getStateData().viewportOffset; + return Transform::Translate(viewportOffset.x, viewportOffset.y, 0); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.h index 3964dee4b933..28293be44521 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.h @@ -36,6 +36,8 @@ class ModalHostViewShadowNode final : public ConcreteViewShadowNode< traits.set(ShadowNodeTraits::Trait::Unstable_uncullableView); return traits; } + + Transform getTransform() const override; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.cpp b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.cpp index e27e93774550..311e4107077a 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.cpp @@ -12,7 +12,9 @@ namespace facebook::react { #ifdef RN_SERIALIZABLE_STATE folly::dynamic ModalHostViewState::getDynamic() const { return folly::dynamic::object("screenWidth", screenSize.width)( - "screenHeight", screenSize.height); + "screenHeight", screenSize.height)( + "viewportOffsetX", viewportOffset.x)( + "viewportOffsetY", viewportOffset.y); } #endif diff --git a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.h b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.h index eec349a35fbb..291719890392 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.h +++ b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.h @@ -26,15 +26,21 @@ class ModalHostViewState final { ModalHostViewState() : screenSize(ModalHostViewScreenSize()) {} ModalHostViewState(Size screenSize_) : screenSize(screenSize_) {}; + ModalHostViewState(Size screenSize_, Point viewportOffset_) + : screenSize(screenSize_), viewportOffset(viewportOffset_) {}; #ifdef RN_SERIALIZABLE_STATE ModalHostViewState(const ModalHostViewState &previousState, folly::dynamic data) : screenSize( - Size{.width = (Float)data["screenWidth"].getDouble(), .height = (Float)data["screenHeight"].getDouble()}) { + Size{.width = (Float)data["screenWidth"].getDouble(), .height = (Float)data["screenHeight"].getDouble()}), + viewportOffset( + Point{.x = data.count("viewportOffsetX") ? (Float)data["viewportOffsetX"].getDouble() : 0.0f, + .y = data.count("viewportOffsetY") ? (Float)data["viewportOffsetY"].getDouble() : 0.0f}) { }; #endif const Size screenSize{}; + const Point viewportOffset{}; #ifdef RN_SERIALIZABLE_STATE folly::dynamic getDynamic() const;