-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Allow portals to have independent layout constraints and scale factor #14315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
7 changes: 7 additions & 0 deletions
7
change/@react-native-windows-codegen-e7b6a9a3-a6de-499d-95bb-1510e5009dd2.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "prerelease", | ||
| "comment": "Fix UpdateState on generated base class", | ||
| "packageName": "@react-native-windows/codegen", | ||
| "email": "[email protected]", | ||
| "dependentChangeType": "patch" | ||
| } |
7 changes: 7 additions & 0 deletions
7
change/react-native-windows-56595f43-5a8f-443b-9594-7de92ea7e45c.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "type": "prerelease", | ||
| "comment": "Allow portals to have independent layout constraints and scale factor", | ||
| "packageName": "react-native-windows", | ||
| "email": "[email protected]", | ||
| "dependentChangeType": "patch" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
vnext/Microsoft.ReactNative/Fabric/AbiPortalShadowNode.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|
|
||
| #include "AbiPortalShadowNode.h" | ||
|
|
||
| #include <Fabric/Composition/ReactCompositionViewComponentBuilder.h> | ||
| #include <react/debug/react_native_assert.h> | ||
| #include <react/renderer/core/LayoutConstraints.h> | ||
| #include <react/renderer/core/LayoutContext.h> | ||
| #include <react/renderer/core/conversions.h> | ||
|
|
||
| #include <utility> | ||
|
|
||
| namespace Microsoft::ReactNative { | ||
|
|
||
| extern const char AbiPortalComponentName[] = "AbiPortal"; | ||
|
|
||
| facebook::react::Size AbiPortalShadowNode::measureContent( | ||
| const facebook::react::LayoutContext &layoutContext, | ||
| const facebook::react::LayoutConstraints &layoutConstraints) const { | ||
| return {0, 0}; // The portal placeholder node shouldn't take up any space | ||
| } | ||
|
|
||
| void AbiPortalShadowNode::layout(facebook::react::LayoutContext layoutContext) { | ||
| ensureUnsealed(); | ||
| auto layoutMetrics = getLayoutMetrics(); | ||
|
|
||
| auto portalOwningShadowNode = ShadowNode::Unshared{}; | ||
|
|
||
| if (getChildren().empty()) { | ||
| return; | ||
| } | ||
|
|
||
| // A Portal should only have a single child | ||
| react_native_assert(getChildren().size() == 1); | ||
|
|
||
| const auto &childNode = getChildren()[0]; | ||
|
|
||
| auto clonedShadowNode = ShadowNode::Unshared{}; | ||
|
|
||
| portalOwningShadowNode = cloneTree(childNode->getFamily(), [&](const ShadowNode &oldShadowNode) { | ||
| clonedShadowNode = oldShadowNode.clone({}); | ||
| return clonedShadowNode; | ||
| }); | ||
| auto portalShadowNode = static_cast<AbiPortalShadowNode *>(portalOwningShadowNode.get()); | ||
|
|
||
| auto &layoutableShadowNode = dynamic_cast<LayoutableShadowNode &>(*clonedShadowNode); | ||
|
|
||
| auto &state = getStateData(); | ||
|
|
||
| facebook::react::LayoutConstraints layoutConstraints; | ||
| layoutConstraints.layoutDirection = layoutMetrics.layoutDirection; | ||
|
|
||
| if (state.userdata) { | ||
| // If the portal component set a state of type IPortalStateData, | ||
| // extract constraint information from it, and use that for layout | ||
| if (auto portalState = state.userdata.try_as<winrt::Microsoft::ReactNative::Composition::IPortalStateData>()) { | ||
| auto stateConstraints = portalState.LayoutConstraints(); | ||
|
|
||
| layoutConstraints.minimumSize = {stateConstraints.MinimumSize.Width, stateConstraints.MinimumSize.Height}; | ||
| layoutConstraints.maximumSize = {stateConstraints.MaximumSize.Width, stateConstraints.MaximumSize.Height}; | ||
| if (stateConstraints.LayoutDirection == winrt::Microsoft::ReactNative::LayoutDirection::LeftToRight) { | ||
| layoutConstraints.layoutDirection = facebook::react::LayoutDirection::LeftToRight; | ||
| } else if (stateConstraints.LayoutDirection == winrt::Microsoft::ReactNative::LayoutDirection::RightToLeft) { | ||
| layoutConstraints.layoutDirection = facebook::react::LayoutDirection::RightToLeft; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Laying out the `ShadowNode` and the subtree starting from it. | ||
| layoutableShadowNode.layoutTree(layoutContext, layoutConstraints); | ||
|
|
||
| auto childLayoutMetrics = layoutableShadowNode.getLayoutMetrics(); | ||
| childLayoutMetrics.frame.origin = {0, 0}; | ||
| layoutableShadowNode.setLayoutMetrics(childLayoutMetrics); | ||
|
|
||
| // Update the list of children to reflect the changes that we made. | ||
| this->children_ = static_cast<AbiPortalShadowNode *>(portalOwningShadowNode.get())->children_; | ||
| } | ||
|
|
||
| void AbiPortalShadowNode::Builder(winrt::Microsoft::ReactNative::IReactViewComponentBuilder builder) noexcept { | ||
| m_builder = builder; | ||
| } | ||
|
|
||
| winrt::Microsoft::ReactNative::IReactViewComponentBuilder AbiPortalShadowNode::Builder() const noexcept { | ||
| return m_builder; | ||
| } | ||
|
|
||
| void AbiPortalShadowNode::Proxy(winrt::Microsoft::ReactNative::ShadowNode proxy) noexcept { | ||
| m_proxy = proxy; | ||
| } | ||
|
|
||
| winrt::Microsoft::ReactNative::ShadowNode AbiPortalShadowNode::Proxy() const noexcept { | ||
| return m_proxy; | ||
| } | ||
|
|
||
| } // namespace Microsoft::ReactNative |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <react/components/rnwcore/EventEmitters.h> | ||
| #include <unordered_map> | ||
| #include "AbiShadowNode.h" | ||
| #include "AbiState.h" | ||
| #include "AbiViewProps.h" | ||
|
|
||
| #include <react/renderer/components/view/ConcreteViewShadowNode.h> | ||
| #include <react/renderer/core/LayoutContext.h> | ||
|
|
||
| namespace Microsoft::ReactNative { | ||
|
|
||
| extern const char AbiPortalComponentName[]; | ||
|
|
||
| class AbiPortalShadowNode final : public facebook::react::ConcreteViewShadowNode< | ||
| AbiPortalComponentName, | ||
| AbiViewProps, | ||
| facebook::react::ViewEventEmitter, | ||
| Microsoft::ReactNative::AbiStateData> { | ||
| public: | ||
| using ConcreteViewShadowNode::ConcreteViewShadowNode; | ||
|
|
||
| static facebook::react::ShadowNodeTraits BaseTraits() { | ||
| auto traits = facebook::react::ShadowNode::BaseTraits(); | ||
| traits.set(facebook::react::ShadowNodeTraits::Trait::FormsStackingContext); | ||
| traits.set(facebook::react::ShadowNodeTraits::Trait::FormsView); | ||
| traits.set(facebook::react::ShadowNodeTraits::Trait::RootNodeKind); | ||
| traits.set(facebook::react::ShadowNodeTraits::Trait::LeafYogaNode); | ||
| traits.set(facebook::react::ShadowNodeTraits::Trait::MeasurableYogaNode); | ||
| return traits; | ||
| } | ||
|
|
||
| facebook::react::Size measureContent( | ||
| const facebook::react::LayoutContext &layoutContext, | ||
| const facebook::react::LayoutConstraints &layoutConstraints) const override; | ||
| void layout(facebook::react::LayoutContext layoutContext) override; | ||
|
|
||
| void OnClone(const facebook::react::ShadowNode &sourceShadowNode) noexcept; | ||
| void Builder(winrt::Microsoft::ReactNative::IReactViewComponentBuilder builder) noexcept; | ||
| winrt::Microsoft::ReactNative::IReactViewComponentBuilder Builder() const noexcept; | ||
| void Proxy(winrt::Microsoft::ReactNative::ShadowNode handle) noexcept; | ||
| winrt::Microsoft::ReactNative::ShadowNode Proxy() const noexcept; | ||
|
|
||
| private: | ||
| winrt::Microsoft::ReactNative::ShadowNode m_proxy{nullptr}; | ||
| winrt::Microsoft::ReactNative::IReactViewComponentBuilder m_builder{nullptr}; | ||
| }; | ||
|
|
||
| } // namespace Microsoft::ReactNative |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of the work here to allow for a separate layout within the portal - is this mean to be reusable by other potential future components who need independent yoga layout, or is the impl modal specific? Are we documenting Portals anywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes future components can use it. -- I'm doing this mostly to unblock our Callout implementation in Office.
--Yeah, more docs needed. At some point we need to do a proper set of documentation on writing custom native components in general.