diff --git a/.ado/jobs/universal.yml b/.ado/jobs/universal.yml index 5599d3f325d..f148bddb6f8 100644 --- a/.ado/jobs/universal.yml +++ b/.ado/jobs/universal.yml @@ -108,6 +108,7 @@ Invoke-WebRequest -UseBasicParsing $winmd2md_url -OutFile $env:TEMP\winmd2md.exe & $env:TEMP\winmd2md.exe /experimental /outputDirectory vnext\target\winmd2md vnext\target\${{ matrix.BuildPlatform }}\${{ matrix.BuildConfiguration }}\Microsoft.ReactNative\Microsoft.ReactNative.winmd displayName: "Generate WinRT API docs" + continueOnError: true - task: PublishBuildArtifacts@1 displayName: Upload WinRT API docs diff --git a/change/react-native-windows-86668219-62b8-4f50-98cd-ca89397c90ff.json b/change/react-native-windows-86668219-62b8-4f50-98cd-ca89397c90ff.json new file mode 100644 index 00000000000..31db8d104ea --- /dev/null +++ b/change/react-native-windows-86668219-62b8-4f50-98cd-ca89397c90ff.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Introduce xamlhost component", + "packageName": "react-native-windows", + "email": "10109130+sharath2727@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/vnext/Microsoft.ReactNative/App.xaml b/vnext/Microsoft.ReactNative/App.xaml new file mode 100644 index 00000000000..038e5a57397 --- /dev/null +++ b/vnext/Microsoft.ReactNative/App.xaml @@ -0,0 +1,5 @@ + + diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp index 6ce1074a63c..a54aae50a14 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp @@ -161,6 +161,13 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::SetFocus(void) { return UiaSetFocusHelper(m_view); } +winrt::IUnknown CompositionDynamicAutomationProvider::TryGetChildSiteLinkAutomationProvider() { + if (m_childSiteLink) { + return m_childSiteLink.AutomationProvider().as(); + } + return nullptr; +} + HRESULT __stdcall CompositionDynamicAutomationProvider::get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal) { if (pRetVal == nullptr) return E_POINTER; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h index 7009a6e21b8..5049a52c4b3 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h @@ -98,6 +98,14 @@ class CompositionDynamicAutomationProvider : public winrt::implements< void AddToSelectionItems(winrt::com_ptr &item); void RemoveFromSelectionItems(winrt::com_ptr &item); + void SetChildSiteLink(winrt::Microsoft::UI::Content::ChildSiteLink childSiteLink) { + m_childSiteLink = childSiteLink; + } + + // If this object is for a ChildSiteLink, returns the ChildSiteLink's automation provider. + // This will be a provider object from the hosted framework (for example, WinUI). + winrt::IUnknown TryGetChildSiteLinkAutomationProvider(); + private: ::Microsoft::ReactNative::ReactTaggedView m_view; winrt::com_ptr m_textProvider; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp index 6ead642c857..e254eb4c367 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp @@ -219,7 +219,8 @@ HRESULT __stdcall CompositionRootAutomationProvider::ElementProviderFromPoint( auto local = rootView->ConvertScreenToLocal({static_cast(x), static_cast(y)}); auto provider = rootView->UiaProviderFromPoint( {static_cast(local.X * rootView->LayoutMetrics().PointScaleFactor), - static_cast(local.Y * rootView->LayoutMetrics().PointScaleFactor)}); + static_cast(local.Y * rootView->LayoutMetrics().PointScaleFactor)}, + {static_cast(x), static_cast(y)}); auto spFragment = provider.try_as(); if (spFragment) { *pRetVal = spFragment.detach(); diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp index 57aa7d14656..6a7685b2877 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp @@ -178,14 +178,12 @@ ContentIslandComponentView::~ContentIslandComponentView() noexcept { void ContentIslandComponentView::MountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept { - assert(false); base_type::MountChildComponentView(childComponentView, index); } void ContentIslandComponentView::UnmountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept { - assert(false); base_type::UnmountChildComponentView(childComponentView, index); } @@ -262,6 +260,12 @@ void ContentIslandComponentView::ConfigureChildSiteLinkAutomation() noexcept { args.AutomationProvider(nullptr); args.Handled(true); }); + + if (m_uiaProvider) { + auto providerImpl = + m_uiaProvider.as(); + providerImpl->SetChildSiteLink(m_childSiteLink); + } } } // namespace winrt::Microsoft::ReactNative::Composition::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp index 2777b76799b..2a39c2a28a9 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp @@ -8,6 +8,7 @@ #include #include +#include "CompositionDynamicAutomationProvider.h" #include "CompositionRootAutomationProvider.h" #include "ReactNativeIsland.h" #include "Theme.h" @@ -275,7 +276,7 @@ facebook::react::Point RootComponentView::getClientOffset() const noexcept { return {}; } -winrt::IInspectable RootComponentView::UiaProviderFromPoint(const POINT &ptPixels) noexcept { +winrt::IUnknown RootComponentView::UiaProviderFromPoint(const POINT &ptPixels, const POINT &ptScreen) noexcept { facebook::react::Point ptDips{ static_cast(ptPixels.x) / m_layoutMetrics.pointScaleFactor, static_cast(ptPixels.y) / m_layoutMetrics.pointScaleFactor}; @@ -295,7 +296,41 @@ winrt::IInspectable RootComponentView::UiaProviderFromPoint(const POINT &ptPixel if (view == nullptr) return nullptr; - return winrt::get_self(view)->EnsureUiaProvider(); + auto uiaProvider = + winrt::get_self(view)->EnsureUiaProvider(); + + // TODO: Avoid exposing CompositionDynamicAutomationProvider in RootComponentView + auto dynamicProvider = + uiaProvider.try_as(); + if (dynamicProvider) { + if (auto childProvider = dynamicProvider->TryGetChildSiteLinkAutomationProvider()) { + // ChildProvider is the the automation provider from the ChildSiteLink. In the case of WinUI, this + // is a pointer to WinUI's internal CUIAHostWindow object. + // It seems odd, but even though this node doesn't behave as a fragment root in our case (the real fragment root + // is the RootComponentView's UIA provider), we still use its IRawElementProviderFragmentRoot -- just so + // we can do the ElementProviderFromPoint call. (this was recommended by the team who did the initial + // architecture work). + if (auto fragmentRoot = childProvider.try_as()) { + com_ptr frag; + // WinUI then does its own hitTest inside the XAML tree. + fragmentRoot->ElementProviderFromPoint( + ptScreen + .x, // Note since we're going through IRawElementProviderFragment the coordinates are in screen space. + ptScreen.y, + frag.put()); + // We return the specific child provider(frag) when hosted XAML has an element + // under the cursor. This satisfies the UIA "element at point" contract and exposes + // the control’s patterns/properties. If the hosted tree finds nothing, we fall back + // to the RNW container’s provider (uiaProvider) to keep the island accessible. + // (A Microsoft_UI_Xaml!CUIAWrapper object) + if (frag) { + return frag.as(); + } + } + } + } + + return uiaProvider; } float RootComponentView::FontSizeMultiplier() const noexcept { diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h index 3a037fc6d61..83f633d212e 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h @@ -64,7 +64,7 @@ struct RootComponentView : RootComponentViewT true false + true diff --git a/vnext/Microsoft.ReactNative/XamlApplication.cpp b/vnext/Microsoft.ReactNative/XamlApplication.cpp new file mode 100644 index 00000000000..450cc7ca8d5 --- /dev/null +++ b/vnext/Microsoft.ReactNative/XamlApplication.cpp @@ -0,0 +1,71 @@ +#include "pch.h" +#include "XamlApplication.h" +#include "Xaml.XamlApplication.g.cpp" + +#include "winrt/Microsoft.UI.Xaml.XamlTypeInfo.h" + +namespace winrt::Microsoft::ReactNative::Xaml::implementation { +using namespace ::winrt::Microsoft::UI::Xaml; +using namespace ::winrt::Microsoft::UI::Xaml::Markup; +using namespace ::winrt::Windows::UI::Xaml::Interop; +XamlApplication::XamlApplication() { + s_current = *this; + + // TODO: It's probably not a good idea to only load the controls pri file, there are other ones too. + auto resourceManager = + winrt::Microsoft::Windows::ApplicationModel::Resources::ResourceManager(L"Microsoft.UI.Xaml.Controls.pri"); + + this->ResourceManagerRequested([resourceManager](auto &&, ResourceManagerRequestedEventArgs args) { + args.CustomResourceManager(resourceManager); + }); + winrt::Microsoft::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread(); + + m_providers.push_back( + winrt::make_self() + .as()); // Default generated provider + m_providers.push_back(winrt::Microsoft::UI::Xaml::XamlTypeInfo::XamlControlsXamlMetaDataProvider()); + + auto winUIResources = winrt::Microsoft::UI::Xaml::Controls::XamlControlsResources(); + Resources().MergedDictionaries().Append(winUIResources); +} + +XamlApplication::~XamlApplication() { + s_current = nullptr; +} + +void XamlApplication::AddMetadataProvider( + winrt::Microsoft::UI::Xaml::Markup::IXamlMetadataProvider const &otherProvider) { + m_providers.push_back(otherProvider); +} + +winrt::Microsoft::UI::Xaml::Markup::IXamlType XamlApplication::GetXamlType( + winrt::Windows::UI::Xaml::Interop::TypeName const &type) { + for (const auto &provider : m_providers) { + if (auto result = provider.GetXamlType(type)) { + return result; + } + } + return nullptr; +} + +winrt::Microsoft::UI::Xaml::Markup::IXamlType XamlApplication::GetXamlType(hstring const &fullName) { + for (const auto &provider : m_providers) { + if (auto result = provider.GetXamlType(fullName)) { + return result; + } + } + + return nullptr; +} +com_array XamlApplication::GetXmlnsDefinitions() { + std::vector<::winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition> allDefinitions; + for (const auto &provider : m_providers) { + const auto &definitions = provider.GetXmlnsDefinitions(); + allDefinitions.insert(allDefinitions.cend(), definitions.cbegin(), definitions.cend()); + } + return winrt::com_array<::winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition>( + allDefinitions.begin(), allDefinitions.end()); +} + +winrt::Microsoft::ReactNative::Xaml::XamlApplication XamlApplication::s_current{nullptr}; +} // namespace winrt::Microsoft::ReactNative::Xaml::implementation diff --git a/vnext/Microsoft.ReactNative/XamlApplication.h b/vnext/Microsoft.ReactNative/XamlApplication.h new file mode 100644 index 00000000000..cb3211ee0e0 --- /dev/null +++ b/vnext/Microsoft.ReactNative/XamlApplication.h @@ -0,0 +1,47 @@ +#pragma once +#include "Xaml.XamlApplication.g.h" + +#include +#include +#include +#include +#include +#include + +#include "winrt/Microsoft.UI.Xaml.Hosting.h" +#include "winrt/Microsoft.UI.Xaml.Interop.h" +#include "winrt/Microsoft.UI.Xaml.Markup.h" +#include "winrt/Microsoft.UI.Xaml.h" + +#include "winrt/Windows.UI.Xaml.Interop.h" + +#include "XamlMetaDataProvider.h" + +namespace winrt::Microsoft::ReactNative::Xaml::implementation { +struct XamlApplication : XamlApplicationT { + XamlApplication(); + ~XamlApplication(); + + static void EnsureCreated() { + if (Current() == nullptr) { + s_current = winrt::make(); + } + } + + static winrt::Microsoft::ReactNative::Xaml::XamlApplication Current() { + return s_current; + } + + void AddMetadataProvider(winrt::Microsoft::UI::Xaml::Markup::IXamlMetadataProvider const &otherProvider); + winrt::Microsoft::UI::Xaml::Markup::IXamlType GetXamlType(winrt::Windows::UI::Xaml::Interop::TypeName const &type); + winrt::Microsoft::UI::Xaml::Markup::IXamlType GetXamlType(hstring const &fullName); + com_array GetXmlnsDefinitions(); + + private: + static winrt::Microsoft::ReactNative::Xaml::XamlApplication s_current; + std::vector m_providers; +}; +} // namespace winrt::Microsoft::ReactNative::Xaml::implementation +namespace winrt::Microsoft::ReactNative::Xaml::factory_implementation { +struct XamlApplication : XamlApplicationT {}; +} // namespace winrt::Microsoft::ReactNative::Xaml::factory_implementation diff --git a/vnext/Microsoft.ReactNative/XamlApplication.idl b/vnext/Microsoft.ReactNative/XamlApplication.idl new file mode 100644 index 00000000000..dd90d7b28a5 --- /dev/null +++ b/vnext/Microsoft.ReactNative/XamlApplication.idl @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "DocString.h" + +namespace Microsoft.ReactNative.Xaml { +[webhosthidden][default_interface] runtimeclass XamlApplication : Microsoft.UI.Xaml.Application, + Microsoft.UI.Xaml.Markup.IXamlMetadataProvider { + DOC_STRING("Initializes a new XamlApplication instance for RNW-hosted WinUI/XAML.") + XamlApplication(); + + DOC_STRING("Ensures the XamlApplication singleton exists.") + static void EnsureCreated(); + + DOC_STRING("Gets the process-wide XamlApplication singleton.") + static XamlApplication Current { + get; + }; + + DOC_STRING("Adds an additional XAML metadata provider to the application.") + void AddMetadataProvider(Microsoft.UI.Xaml.Markup.IXamlMetadataProvider otherProvider); +} +} // namespace Microsoft.ReactNative.Xaml diff --git a/vnext/Microsoft.ReactNative/XamlHost.cpp b/vnext/Microsoft.ReactNative/XamlHost.cpp new file mode 100644 index 00000000000..5b6873b9bbf --- /dev/null +++ b/vnext/Microsoft.ReactNative/XamlHost.cpp @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" + +#include "XamlApplication.h" +#include "XamlHost.h" + +#if defined(RNW_NEW_ARCH) + +#include "..\codegen\react\components\rnwcore\XamlHost.g.h" + +namespace winrt::Microsoft::ReactNative { + +struct XamlHostComponentView : public winrt::implements, + ::Microsoft::ReactNativeSpecs::BaseXamlHost { + void InitializeContentIsland( + const winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView &islandView) noexcept { + winrt::Microsoft::ReactNative::Xaml::implementation::XamlApplication::EnsureCreated(); + + m_xamlIsland = winrt::Microsoft::UI::Xaml::XamlIsland{}; + + islandView.Connect(m_xamlIsland.ContentIsland()); + } + + void MountChildComponentView( + const winrt::Microsoft::ReactNative::ComponentView & /*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept override { + // Add the xaml child to the m_xamlIsland here. + auto childXamlControl = args.Child().UserData().as(); + if (childXamlControl) { + auto xamlElement = childXamlControl.GetXamlElement(); + m_xamlIsland.Content(xamlElement); + } + } + + void UnmountChildComponentView( + const winrt::Microsoft::ReactNative::ComponentView & /*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &) noexcept override { + m_xamlIsland.Content(nullptr); + } + + private: + winrt::Microsoft::UI::Xaml::XamlIsland m_xamlIsland{nullptr}; +}; + +} // namespace winrt::Microsoft::ReactNative + +void RegisterXamlHostComponentView(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) { + ::Microsoft::ReactNativeSpecs::RegisterXamlHostNativeComponent( + packageBuilder, + [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { + builder.SetContentIslandComponentViewInitializer( + [](const winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView &islandView) noexcept { + auto userData = winrt::make_self(); + userData->InitializeContentIsland(islandView); + islandView.UserData(*userData); + }); + }); +} + +#endif // defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3) diff --git a/vnext/Microsoft.ReactNative/XamlHost.h b/vnext/Microsoft.ReactNative/XamlHost.h new file mode 100644 index 00000000000..7abc42b8241 --- /dev/null +++ b/vnext/Microsoft.ReactNative/XamlHost.h @@ -0,0 +1,7 @@ +#pragma once + +#if defined(RNW_NEW_ARCH) + +void RegisterXamlHostComponentView(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder); + +#endif // defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3) diff --git a/vnext/Shared/Shared.vcxitems b/vnext/Shared/Shared.vcxitems index 1462b1004f6..58f3b3a4643 100644 --- a/vnext/Shared/Shared.vcxitems +++ b/vnext/Shared/Shared.vcxitems @@ -134,6 +134,16 @@ $(ReactNativeWindowsDir)Microsoft.ReactNative\ReactNativeAppBuilder.idl Code + + + true + $(ReactNativeWindowsDir)Microsoft.ReactNative\XamlApplication.idl + Code + + + true + $(ReactNativeWindowsDir)Microsoft.ReactNative\XamlApplication.idl + Code @@ -237,6 +247,16 @@ $(MSBuildThisFileDirectory)..\Microsoft.ReactNative\ReactNativeAppBuilder.idl Code + + + true + $(MSBuildThisFileDirectory)..\Microsoft.ReactNative\XamlApplication.idl + Code + + + true + $(MSBuildThisFileDirectory)..\Microsoft.ReactNative\XamlApplication.idl + Code $(MSBuildThisFileDirectory)..\Microsoft.ReactNative\IJSValueReader.idl @@ -600,6 +620,8 @@ + + @@ -615,4 +637,7 @@ NotUsing - \ No newline at end of file + + + + diff --git a/vnext/overrides.json b/vnext/overrides.json index 63b78c5e7f0..eb3e0884bcb 100644 --- a/vnext/overrides.json +++ b/vnext/overrides.json @@ -694,6 +694,18 @@ "file": "src-win/src/private/specs_DEPRECATED/modules/NativePlatformConstantsWindows.js", "baseFile": "packages/react-native/src/private/specs_DEPRECATED/modules/NativePlatformConstantsAndroid.js", "baseHash": "365c5df75b38b129d364af3f6700cb206ce5bd2a" + }, + { + "type": "platform", + "file": "src-win/Libraries/Components/Xaml/XamlHost.d.ts" + }, + { + "type": "platform", + "file": "src-win/Libraries/Components/Xaml/XamlHost.windows.js" + }, + { + "type": "platform", + "file": "src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js" } ] } \ No newline at end of file diff --git a/vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts b/vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts new file mode 100644 index 00000000000..a69cfafe0be --- /dev/null +++ b/vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * @format + * @flow + */ +/// +import type {ViewProps} from 'react-native'; +export interface XamlHostProps extends ViewProps { + label: string; +} +declare const _default: import('react-native/Libraries/Utilities/codegenNativeComponent').NativeComponentType; +export default _default; diff --git a/vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js b/vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js new file mode 100644 index 00000000000..723810b17a4 --- /dev/null +++ b/vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js @@ -0,0 +1,7 @@ +/** + * @format + * @flow + */ + +import XamlHost from '../../../src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent'; +export default XamlHost; diff --git a/vnext/src-win/index.windows.js b/vnext/src-win/index.windows.js index 14ac2344540..8f368fe05fe 100644 --- a/vnext/src-win/index.windows.js +++ b/vnext/src-win/index.windows.js @@ -372,6 +372,9 @@ module.exports = { get AppTheme() { return require('./Libraries/AppTheme/AppTheme').AppTheme; }, + get XamlHost() { + return require('./Libraries/Components/Xaml/XamlHost').default; + }, } as ReactNativePublicAPI; if (__DEV__) { diff --git a/vnext/src-win/index.windows.js.flow b/vnext/src-win/index.windows.js.flow index 6942181c0c3..d601455ba73 100644 --- a/vnext/src-win/index.windows.js.flow +++ b/vnext/src-win/index.windows.js.flow @@ -469,6 +469,7 @@ export {HandledEventPhase } from './Libraries/Components/View/ViewPropTypes' export {default as ViewWindows} from './Libraries/Components/View/View'; export {AppTheme} from './Libraries/AppTheme/AppTheme'; +export {default as XamlHost} from './Libraries/Components/Xaml/XamlHost'; // End Windows Specific exports // #endregion diff --git a/vnext/src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js b/vnext/src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js new file mode 100644 index 00000000000..4b0fc158fd8 --- /dev/null +++ b/vnext/src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js @@ -0,0 +1,20 @@ +/** + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * @format + * @flow + */ + +'use strict'; + +import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import type {HostComponent} from '../../../../../src/private/types/HostComponent'; + +type XamlHostProps = $ReadOnly<{| + ...ViewProps, +|}>; + +type NativeType = HostComponent; + +export default (codegenNativeComponent('XamlHost'): NativeType);