diff --git a/change/react-native-windows-1fbec1a3-51f6-4e89-ac75-86846570013e.json b/change/react-native-windows-1fbec1a3-51f6-4e89-ac75-86846570013e.json
new file mode 100644
index 00000000000..2d1a9520d1f
--- /dev/null
+++ b/change/react-native-windows-1fbec1a3-51f6-4e89-ac75-86846570013e.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "Enable basic XamlIsland in rntester within playground app when UseExperimentalWinUI3 is true",
+ "packageName": "react-native-windows",
+ "email": "50150435+JesseCol@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/packages/@react-native-windows/tester/src/js/examples-win/XAML/FabricXamlExample.js b/packages/@react-native-windows/tester/src/js/examples-win/XAML/FabricXamlExample.js
new file mode 100644
index 00000000000..fe0680ec259
--- /dev/null
+++ b/packages/@react-native-windows/tester/src/js/examples-win/XAML/FabricXamlExample.js
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) Microsoft Corporation.
+ * Licensed under the MIT License.
+ * @format
+ * @flow
+ */
+
+'use strict';
+
+// Temporary test example for UseExperimentalWinUI3=true
+// Remove when we get react-native-xaml working well for Fabric
+
+import React, {useState} from 'react';
+import {Alert, Button, Text, View, ScrollView} from 'react-native';
+import {CalendarView} from 'sample-custom-component';
+
+const XamlContentExample = () => {
+ const [selectedDate, setSelectedDate] = useState(true);
+
+ return (
+
+
+
+
+ );
+};
+
+exports.displayName = 'XamlFabricExample';
+exports.framework = 'React';
+exports.category = 'UI';
+exports.title = 'Xaml WinUI3 (Experimental, for Fabric)';
+exports.description =
+ 'Requires UseExperimentalWinUI3 - Xaml content that works in Fabric';
+
+exports.examples = [
+ {
+ title: 'Xaml WinUI3 (Experimental, for Fabric)',
+ render: function (): React.Node {
+ return ;
+ },
+ },
+];
diff --git a/packages/@react-native-windows/tester/src/js/utils/RNTesterList.windows.js b/packages/@react-native-windows/tester/src/js/utils/RNTesterList.windows.js
index 2e9d60dd9a4..d6eabdbb776 100644
--- a/packages/@react-native-windows/tester/src/js/utils/RNTesterList.windows.js
+++ b/packages/@react-native-windows/tester/src/js/utils/RNTesterList.windows.js
@@ -176,6 +176,11 @@ const Components: Array = [
category: 'UI',
module: require('../examples-win/XAML/XAMLExample'),
},
+ {
+ key: 'FabricXaml',
+ category: 'UI',
+ module: require('../examples-win/XAML/FabricXamlExample'),
+ },
{
key: 'LegacyControlStyleTest',
module: require('../examples-win/LegacyTests/ControlStyleTestPage'),
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap
index e74cc513012..d0057572694 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap
@@ -6350,3 +6350,82 @@ exports[`Home UIA Tree Dump XMLHttpRequest 1`] = `
},
}
`;
+
+exports[`Home UIA Tree Dump Xaml WinUI3 (Experimental, for Fabric) 1`] = `
+{
+ "Automation Tree": {
+ "AutomationId": "Xaml WinUI3 (Experimental, for Fabric)",
+ "ControlType": 50026,
+ "IsKeyboardFocusable": true,
+ "LocalizedControlType": "group",
+ "Name": "Xaml WinUI3 (Experimental, for Fabric) Requires UseExperimentalWinUI3 - Xaml content that works in Fabric",
+ "__Children": [
+ {
+ "AutomationId": "",
+ "ControlType": 50020,
+ "LocalizedControlType": "text",
+ "Name": "Xaml WinUI3 (Experimental, for Fabric)",
+ },
+ {
+ "AutomationId": "",
+ "ControlType": 50020,
+ "LocalizedControlType": "text",
+ "Name": "Requires UseExperimentalWinUI3 - Xaml content that works in Fabric",
+ },
+ ],
+ },
+ "Component Tree": {
+ "Type": "Microsoft.ReactNative.Composition.ViewComponentView",
+ "_Props": {
+ "AccessibilityLabel": "Xaml WinUI3 (Experimental, for Fabric) Requires UseExperimentalWinUI3 - Xaml content that works in Fabric",
+ "TestId": "Xaml WinUI3 (Experimental, for Fabric)",
+ },
+ "__Children": [
+ {
+ "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
+ "_Props": {},
+ },
+ {
+ "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
+ "_Props": {},
+ },
+ ],
+ },
+ "Visual Tree": {
+ "Brush": {
+ "Brush Type": "ColorBrush",
+ "Color": "rgba(255, 255, 255, 255)",
+ },
+ "Comment": "Xaml WinUI3 (Experimental, for Fabric)",
+ "Offset": "0, 0, 0",
+ "Size": "966, 78",
+ "Visual Type": "SpriteVisual",
+ "__Children": [
+ {
+ "Offset": "16, 16, 0",
+ "Size": "305, 25",
+ "Visual Type": "SpriteVisual",
+ "__Children": [
+ {
+ "Offset": "0, 0, 0",
+ "Size": "305, 25",
+ "Visual Type": "SpriteVisual",
+ },
+ ],
+ },
+ {
+ "Offset": "16, 45, 0",
+ "Size": "934, 17",
+ "Visual Type": "SpriteVisual",
+ "__Children": [
+ {
+ "Offset": "0, 0, 0",
+ "Size": "934, 17",
+ "Visual Type": "SpriteVisual",
+ },
+ ],
+ },
+ ],
+ },
+}
+`;
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap b/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap
index 4c67fc34d5d..fbcdd6150eb 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap
@@ -87138,3 +87138,204 @@ exports[`snapshotAllPages XMLHttpRequest 6`] = `
`;
+
+exports[`snapshotAllPages Xaml WinUI3 (Experimental, for Fabric) 1`] = `
+
+
+
+
+
+
+
+ Before Button
+
+
+
+
+
+ Xaml CalendarView control. Selected date:
+
+
+
+
+
+
+ After Button
+
+
+
+
+
+
+
+`;
diff --git a/packages/e2e-test-app/test/visitAllPages.test.ts b/packages/e2e-test-app/test/visitAllPages.test.ts
index 7251fe12f89..8e92597bfe2 100644
--- a/packages/e2e-test-app/test/visitAllPages.test.ts
+++ b/packages/e2e-test-app/test/visitAllPages.test.ts
@@ -38,7 +38,8 @@ describe('visitAllPages', () => {
component === 'Moving Light Example' ||
component === 'Drawing Island Example' ||
component === 'Fabric Native Component' ||
- component === 'Fabric Native Component Yoga'
+ component === 'Fabric Native Component Yoga' ||
+ component === 'Xaml WinUI3 (Experimental, for Fabric)'
) {
continue; // disable fabric specific tests
}
diff --git a/packages/playground/windows/playground-composition/Playground-Composition.cpp b/packages/playground/windows/playground-composition/Playground-Composition.cpp
index e1d010fcd62..bd2d52a28db 100644
--- a/packages/playground/windows/playground-composition/Playground-Composition.cpp
+++ b/packages/playground/windows/playground-composition/Playground-Composition.cpp
@@ -103,9 +103,12 @@ struct EllipseReactPackageProvider
struct CompReactPackageProvider
: winrt::implements {
public: // IReactPackageProvider
- void CreatePackage(winrt::Microsoft::ReactNative::IReactPackageBuilder const & /*packageBuilder*/) noexcept {
- // Reenable RegisterCustomComponent when we have better XamlIsland hosting support
- // RegisterCustomComponent(packageBuilder);
+ void CreatePackage(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept {
+#ifdef USE_EXPERIMENTAL_WINUI3
+ RegisterCustomComponent(packageBuilder);
+#else
+ UNREFERENCED_PARAMETER(packageBuilder);
+#endif // USE_EXPERIMENTAL_WINUI3
}
};
@@ -739,7 +742,7 @@ _Use_decl_annotations_ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE, PSTR
#ifdef USE_EXPERIMENTAL_WINUI3
// Island-support: Create our custom Xaml App object. This is needed to properly use the controls and metadata
// in Microsoft.ui.xaml.controls.dll.
- // auto playgroundApp{winrt::make()};
+ auto playgroundApp{winrt::make()};
#endif
return RunPlayground(showCmd, false);
diff --git a/packages/sample-custom-component/src/FabricXamlCalendarViewNativeComponent.ts b/packages/sample-custom-component/src/FabricXamlCalendarViewNativeComponent.ts
new file mode 100644
index 00000000000..bd8d765083e
--- /dev/null
+++ b/packages/sample-custom-component/src/FabricXamlCalendarViewNativeComponent.ts
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) Microsoft Corporation.
+ * Licensed under the MIT License.
+ * @format
+ * @flow
+ */
+
+'use strict';
+
+// Temporary test example for UseExperimentalWinUI3=true
+// Remove when we get react-native-xaml working well for Fabric
+
+import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
+import type {ViewProps} from 'react-native';
+import type {DirectEventHandler} from 'react-native/Libraries/Types/CodegenTypes';
+
+type SelectedDatesChangedEvent = Readonly<{
+ value: boolean;
+ startDate: string;
+}>;
+
+export interface CalendarViewProps extends ViewProps {
+ label: string;
+ onSelectedDatesChanged?: DirectEventHandler;
+}
+
+export default codegenNativeComponent('CalendarView');
diff --git a/packages/sample-custom-component/src/index.ts b/packages/sample-custom-component/src/index.ts
index a397cf026bd..182564080ea 100644
--- a/packages/sample-custom-component/src/index.ts
+++ b/packages/sample-custom-component/src/index.ts
@@ -3,8 +3,11 @@ import type {MovingLightHandle} from './MovingLight';
import DrawingIsland from './DrawingIsland';
+import CalendarView from './FabricXamlCalendarViewNativeComponent'
+
export {
DrawingIsland,
MovingLight,
MovingLightHandle,
+ CalendarView,
};
\ No newline at end of file
diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/CalendarView.cpp b/packages/sample-custom-component/windows/SampleCustomComponent/CalendarView.cpp
new file mode 100644
index 00000000000..977b221d943
--- /dev/null
+++ b/packages/sample-custom-component/windows/SampleCustomComponent/CalendarView.cpp
@@ -0,0 +1,74 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+#include "pch.h"
+
+#include "CalendarView.h"
+
+#if defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3)
+
+#include "codegen/react/components/SampleCustomComponent/CalendarView.g.h"
+
+#include
+
+namespace winrt::SampleCustomComponent {
+
+// This is a "toy" implementation of Xaml's CalendarView, just for bringup and testing.
+// When UseExperimentalWinUI3 and UseNewArchitecture are both true, it will host a
+// CalendarView control in a XamlIsland. But we only expose a few APIs right now.
+// Later, we'll expose this through react-native-xaml.
+
+struct CalendarViewComponentView : public winrt::implements,
+ Codegen::BaseCalendarView {
+ void InitializeContentIsland(
+ const winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView &islandView) noexcept {
+ m_xamlIsland = winrt::Microsoft::UI::Xaml::XamlIsland{};
+ m_calendarView = winrt::Microsoft::UI::Xaml::Controls::CalendarView{};
+ m_xamlIsland.Content(m_calendarView);
+ islandView.Connect(m_xamlIsland.ContentIsland());
+
+ m_calendarView.SelectedDatesChanged([this](auto &&, auto &&) {
+ if (auto emitter = EventEmitter()) {
+ Codegen::CalendarView_OnSelectedDatesChanged args;
+ auto selectedDates = m_calendarView.SelectedDates();
+ if (selectedDates.Size() == 0) {
+ args.startDate = "(none)";
+ } else {
+ auto firstSelectedDate = selectedDates.GetAt(0);
+
+ auto tt = winrt::clock::to_time_t(firstSelectedDate);
+ tm local{};
+ localtime_s(&local, &tt);
+ auto timeStr = std::put_time(&local, "%F");
+
+ std::stringstream ss;
+ ss << (timeStr._Tptr->tm_year + 1900) << "-" << (timeStr._Tptr->tm_mon + 1) << "-" << timeStr._Tptr->tm_mday;
+
+ args.startDate = ss.str();
+ }
+ emitter->onSelectedDatesChanged(args);
+ }
+ });
+ }
+
+ private:
+ winrt::Microsoft::UI::Xaml::XamlIsland m_xamlIsland{nullptr};
+ winrt::Microsoft::UI::Xaml::Controls::CalendarView m_calendarView{nullptr};
+};
+
+} // namespace winrt::SampleCustomComponent
+
+void RegisterCalendarViewComponentView(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) {
+ winrt::SampleCustomComponent::Codegen::RegisterCalendarViewNativeComponent<
+ winrt::SampleCustomComponent::CalendarViewComponentView>(
+ 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/packages/sample-custom-component/windows/SampleCustomComponent/CalendarView.h b/packages/sample-custom-component/windows/SampleCustomComponent/CalendarView.h
new file mode 100644
index 00000000000..2ef17343b84
--- /dev/null
+++ b/packages/sample-custom-component/windows/SampleCustomComponent/CalendarView.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#if defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3)
+
+void RegisterCalendarViewComponentView(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder);
+
+#endif // defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3)
diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/ReactPackageProvider.cpp b/packages/sample-custom-component/windows/SampleCustomComponent/ReactPackageProvider.cpp
index 16d46adb132..6e8affd9f6e 100644
--- a/packages/sample-custom-component/windows/SampleCustomComponent/ReactPackageProvider.cpp
+++ b/packages/sample-custom-component/windows/SampleCustomComponent/ReactPackageProvider.cpp
@@ -7,6 +7,7 @@
#include "ReactPackageProvider.g.cpp"
#endif
+#include "CalendarView.h"
#include "DrawingIsland.h"
#include "MovingLight.h"
@@ -21,6 +22,10 @@ void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuil
RegisterDrawingIslandComponentView(packageBuilder);
RegisterMovingLightNativeComponent(packageBuilder);
#endif // #ifdef RNW_NEW_ARCH
+
+#if defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3)
+ RegisterCalendarViewComponentView(packageBuilder);
+#endif // #if defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3)
}
} // namespace winrt::SampleCustomComponent::implementation
diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj b/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj
index 81665a9aeaf..0ef07d3aeb9 100644
--- a/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj
+++ b/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj
@@ -99,6 +99,7 @@
+
DrawingIsland.idl
@@ -121,6 +122,7 @@
ReactPackageProvider.idl
+
diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/CalendarView.g.h b/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/CalendarView.g.h
new file mode 100644
index 00000000000..5246a8570b9
--- /dev/null
+++ b/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/CalendarView.g.h
@@ -0,0 +1,217 @@
+
+/*
+ * This file is auto-generated from CalendarViewNativeComponent spec file in flow / TypeScript.
+ */
+// clang-format off
+#pragma once
+
+#include
+
+#ifdef RNW_NEW_ARCH
+#include
+
+#include
+#include
+#endif // #ifdef RNW_NEW_ARCH
+
+#ifdef RNW_NEW_ARCH
+
+namespace winrt::SampleCustomComponent::Codegen {
+
+REACT_STRUCT(CalendarViewProps)
+struct CalendarViewProps : winrt::implements {
+ CalendarViewProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom)
+ : ViewProps(props)
+ {
+ if (cloneFrom) {
+ auto cloneFromProps = cloneFrom.as();
+ label = cloneFromProps->label;
+ }
+ }
+
+ void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept {
+ winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this);
+ }
+
+ REACT_FIELD(label)
+ std::string label;
+
+ const winrt::Microsoft::ReactNative::ViewProps ViewProps;
+};
+
+REACT_STRUCT(CalendarView_OnSelectedDatesChanged)
+struct CalendarView_OnSelectedDatesChanged {
+ REACT_FIELD(value)
+ bool value{};
+
+ REACT_FIELD(startDate)
+ std::string startDate;
+};
+
+struct CalendarViewEventEmitter {
+ CalendarViewEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter)
+ : m_eventEmitter(eventEmitter) {}
+
+ using OnSelectedDatesChanged = CalendarView_OnSelectedDatesChanged;
+
+ void onSelectedDatesChanged(OnSelectedDatesChanged &value) const {
+ m_eventEmitter.DispatchEvent(L"selectedDatesChanged", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) {
+ winrt::Microsoft::ReactNative::WriteValue(writer, value);
+ });
+ }
+
+ private:
+ winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr};
+};
+
+template
+struct BaseCalendarView {
+
+ virtual void UpdateProps(
+ const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
+ const winrt::com_ptr &newProps,
+ const winrt::com_ptr &/*oldProps*/) noexcept {
+ m_props = newProps;
+ }
+
+ // UpdateLayoutMetrics will only be called if this method is overridden
+ virtual void UpdateLayoutMetrics(
+ const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
+ const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/,
+ const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept {
+ }
+
+ // UpdateState will only be called if this method is overridden
+ virtual void UpdateState(
+ const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
+ const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept {
+ }
+
+ virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept {
+ m_eventEmitter = eventEmitter;
+ }
+
+ // MountChildComponentView will only be called if this method is overridden
+ virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
+ const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept {
+ }
+
+ // UnmountChildComponentView will only be called if this method is overridden
+ virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
+ const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept {
+ }
+
+ // Initialize will only be called if this method is overridden
+ virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept {
+ }
+
+ // CreateVisual will only be called if this method is overridden
+ virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
+ return view.as().Compositor().CreateSpriteVisual();
+ }
+
+ // FinalizeUpdate will only be called if this method is overridden
+ virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
+ winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept {
+ }
+
+
+
+ const std::shared_ptr& EventEmitter() const { return m_eventEmitter; }
+ const winrt::com_ptr& Props() const { return m_props; }
+
+private:
+ winrt::com_ptr m_props;
+ std::shared_ptr m_eventEmitter;
+};
+
+template
+void RegisterCalendarViewNativeComponent(
+ winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder,
+ std::function builderCallback) noexcept {
+ packageBuilder.as().AddViewComponent(
+ L"CalendarView", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept {
+ auto compBuilder = builder.as();
+
+ builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props,
+ const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept {
+ return winrt::make(props, cloneFrom);
+ });
+
+ builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
+ const winrt::Microsoft::ReactNative::IComponentProps &newProps,
+ const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept {
+ auto userData = view.UserData().as();
+ userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr);
+ });
+
+ compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
+ const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics,
+ const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept {
+ auto userData = view.UserData().as();
+ userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics);
+ });
+
+ builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
+ const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept {
+ auto userData = view.UserData().as();
+ userData->UpdateEventEmitter(std::make_shared(eventEmitter));
+ });
+
+ if constexpr (&TUserData::FinalizeUpdate != &BaseCalendarView::FinalizeUpdate) {
+ builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
+ winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept {
+ auto userData = view.UserData().as();
+ userData->FinalizeUpdate(view, mask);
+ });
+ }
+
+ if constexpr (&TUserData::UpdateState != &BaseCalendarView::UpdateState) {
+ builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
+ const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept {
+ auto userData = view.UserData().as();
+ userData->member(view, newState);
+ });
+ }
+
+ if constexpr (&TUserData::MountChildComponentView != &BaseCalendarView::MountChildComponentView) {
+ builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
+ const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept {
+ auto userData = view.UserData().as();
+ return userData->MountChildComponentView(view, args);
+ });
+ }
+
+ if constexpr (&TUserData::UnmountChildComponentView != &BaseCalendarView::UnmountChildComponentView) {
+ builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
+ const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept {
+ auto userData = view.UserData().as();
+ return userData->UnmountChildComponentView(view, args);
+ });
+ }
+
+ compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
+ auto userData = winrt::make_self();
+ if constexpr (&TUserData::Initialize != &BaseCalendarView::Initialize) {
+ userData->Initialize(view);
+ }
+ view.UserData(*userData);
+ });
+
+ if constexpr (&TUserData::CreateVisual != &BaseCalendarView::CreateVisual) {
+ compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
+ auto userData = view.UserData().as();
+ return userData->CreateVisual(view);
+ });
+ }
+
+ // Allow app to further customize the builder
+ if (builderCallback) {
+ builderCallback(compBuilder);
+ }
+ });
+}
+
+} // namespace winrt::SampleCustomComponent::Codegen
+
+#endif // #ifdef RNW_NEW_ARCH
diff --git a/vnext/Microsoft.ReactNative.Cxx/XamlUtils.h b/vnext/Microsoft.ReactNative.Cxx/XamlUtils.h
index c4287ca3cab..71cbd24cbe2 100644
--- a/vnext/Microsoft.ReactNative.Cxx/XamlUtils.h
+++ b/vnext/Microsoft.ReactNative.Cxx/XamlUtils.h
@@ -54,6 +54,18 @@ inline Application TryGetCurrentApplication() noexcept {
}
}
+// In the legacy architecture, RNW uses a Uwp Xaml app as the groundwork for the UI.
+// In the new architecture, WinUI3 Xaml may be involved, but only as XamlIslands -- leaf nodes in the RNW content.
+// This function returns the Uwp/System Xaml Application if we're running in the legacy architecture and Xaml is
+// running, and null if otherwise.
+inline Application TryGetCurrentUwpXamlApplication() noexcept {
+#ifdef USE_WINUI3
+ return nullptr;
+#else
+ return TryGetCurrentApplication();
+#endif
+}
+
// Using Windows::UI::ColorHelper causes the process to load Windows.UI.Xaml.dll which is not needed just to fill a
// Color struct
inline winrt::Windows::UI::Color FromArgb(uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Theme.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Theme.cpp
index 2c4a3e72ad3..8a86a67c0f2 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/Theme.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Theme.cpp
@@ -124,7 +124,7 @@ bool Theme::TryGetPlatformColor(const std::string &platformColor, winrt::Windows
#ifndef CORE_ABI
// If XAML is loaded, look in application resources
- if (xaml::TryGetCurrentApplication()) {
+ if (xaml::TryGetCurrentUwpXamlApplication()) {
const auto appResources{xaml::Application::Current().Resources()};
const auto boxedResourceName{winrt::box_value(winrt::to_hstring(platformColor))};
if (appResources.HasKey(boxedResourceName)) {
diff --git a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorUtils.cpp b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorUtils.cpp
index 589290f6f71..f87ce95c057 100644
--- a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorUtils.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorUtils.cpp
@@ -16,7 +16,7 @@ winrt::Windows::UI::Color ResolvePlatformColor(const std::vector &s
for (auto platformColor : semanticItems) {
#ifndef CORE_ABI
// If XAML is loaded, look in application resources
- if (xaml::TryGetCurrentApplication()) {
+ if (xaml::TryGetCurrentUwpXamlApplication()) {
xaml::Media::Brush brush{Microsoft::ReactNative::BrushFromColorObject(platformColor)};
if (auto scb{brush.try_as()}) {
return scb.Color();
diff --git a/vnext/Microsoft.ReactNative/Modules/AlertModule.cpp b/vnext/Microsoft.ReactNative/Modules/AlertModule.cpp
index 04de7fc2240..d16763e40da 100644
--- a/vnext/Microsoft.ReactNative/Modules/AlertModule.cpp
+++ b/vnext/Microsoft.ReactNative/Modules/AlertModule.cpp
@@ -220,7 +220,7 @@ void Alert::ProcessPendingAlertRequests() noexcept {
if (pendingAlerts.empty())
return;
- if (xaml::TryGetCurrentApplication()) {
+ if (xaml::TryGetCurrentUwpXamlApplication()) {
ProcessPendingAlertRequestsXaml();
}
#ifdef USE_FABRIC
@@ -230,6 +230,7 @@ void Alert::ProcessPendingAlertRequests() noexcept {
}
#endif
}
+
Alert::Constants Alert::GetConstants() noexcept {
return m_constants;
}
diff --git a/vnext/Microsoft.ReactNative/Modules/AppStateModule.cpp b/vnext/Microsoft.ReactNative/Modules/AppStateModule.cpp
index 89d9a0cd294..185b31c22d4 100644
--- a/vnext/Microsoft.ReactNative/Modules/AppStateModule.cpp
+++ b/vnext/Microsoft.ReactNative/Modules/AppStateModule.cpp
@@ -21,7 +21,7 @@ void AppState::Initialize(winrt::Microsoft::ReactNative::ReactContext const &rea
// We need to register for notifications from the XAML thread.
if (auto dispatcher = reactContext.UIDispatcher()) {
dispatcher.Post([this]() {
- auto currentApp = xaml::TryGetCurrentApplication();
+ auto currentApp = xaml::TryGetCurrentUwpXamlApplication();
if (!IsWinUI3Island() && currentApp != nullptr) {
#ifndef USE_WINUI3
diff --git a/vnext/Microsoft.ReactNative/Modules/AppThemeModuleUwp.cpp b/vnext/Microsoft.ReactNative/Modules/AppThemeModuleUwp.cpp
index dd6960e0508..6b3259f3b00 100644
--- a/vnext/Microsoft.ReactNative/Modules/AppThemeModuleUwp.cpp
+++ b/vnext/Microsoft.ReactNative/Modules/AppThemeModuleUwp.cpp
@@ -44,7 +44,7 @@ static const React::ReactPropertyIdNotifications()), WM_THEMECHANGED, [this](const auto &, const auto &) {
@@ -77,7 +77,7 @@ void AppThemeHolder::SetCallback(
void AppThemeHolder::NotifyHighContrastChanged() noexcept {
m_appThemeData.isHighContrast =
- xaml::TryGetCurrentApplication() ? m_accessibilitySettings.HighContrast() : IsInHighContrastWin32();
+ xaml::TryGetCurrentUwpXamlApplication() ? m_accessibilitySettings.HighContrast() : IsInHighContrastWin32();
m_appThemeData.highContrastColors.ButtonFaceColor =
FormatRGB(m_uiSettings.UIElementColor(winrt::UIElementType::ButtonFace));
m_appThemeData.highContrastColors.ButtonTextColor =
diff --git a/vnext/Microsoft.ReactNative/Modules/AppearanceModule.cpp b/vnext/Microsoft.ReactNative/Modules/AppearanceModule.cpp
index fd16f26a606..5a2791c2bd6 100644
--- a/vnext/Microsoft.ReactNative/Modules/AppearanceModule.cpp
+++ b/vnext/Microsoft.ReactNative/Modules/AppearanceModule.cpp
@@ -50,7 +50,7 @@ ApplicationTheme CurrentThemeFromUISettings(const winrt::Windows::UI::ViewManage
ApplicationTheme Appearance::GetCurrentTheme() noexcept {
assert(m_context.UIDispatcher().HasThreadAccess()); // xaml::Application is only accessible on the UI thread
- if (auto currentApp = xaml::TryGetCurrentApplication()) {
+ if (auto currentApp = xaml::TryGetCurrentUwpXamlApplication()) {
return currentApp.RequestedTheme();
}
@@ -74,7 +74,7 @@ void Appearance::RequeryTheme() noexcept {
void Appearance::InitOnUIThread(const Mso::React::IReactContext &context) noexcept {
xaml::ApplicationTheme theme = ApplicationTheme::Light;
- if (auto currentApp = xaml::TryGetCurrentApplication()) {
+ if (auto currentApp = xaml::TryGetCurrentUwpXamlApplication()) {
theme = currentApp.RequestedTheme();
} else {
theme = CurrentThemeFromUISettings(winrt::Windows::UI::ViewManagement::UISettings());
diff --git a/vnext/Microsoft.ReactNative/Modules/DeviceInfoModule.cpp b/vnext/Microsoft.ReactNative/Modules/DeviceInfoModule.cpp
index ea74ae6b188..610e08bca0b 100644
--- a/vnext/Microsoft.ReactNative/Modules/DeviceInfoModule.cpp
+++ b/vnext/Microsoft.ReactNative/Modules/DeviceInfoModule.cpp
@@ -36,7 +36,7 @@ DeviceInfoHolder::DeviceInfoHolder(const Mso::React::IReactContext &context) : m
}
void DeviceInfoHolder::InitDeviceInfoHolder(const Mso::React::IReactContext &context) noexcept {
- if (xaml::TryGetCurrentApplication() || IsFabricEnabled(context.Properties())) {
+ if (xaml::TryGetCurrentUwpXamlApplication() || IsFabricEnabled(context.Properties())) {
auto deviceInfoHolder = std::make_shared(context);
deviceInfoHolder->updateDeviceInfo();
@@ -51,7 +51,7 @@ void DeviceInfoHolder::InitDeviceInfoHolder(const Mso::React::IReactContext &con
}
#endif
- if (xaml::TryGetCurrentApplication()) {
+ if (xaml::TryGetCurrentUwpXamlApplication()) {
if (auto window = xaml::Window::Current()) {
auto const &coreWindow = window.CoreWindow();
@@ -157,7 +157,7 @@ void DeviceInfoHolder::SetCallback(
}
void DeviceInfoHolder::updateDeviceInfo() noexcept {
- if (xaml::TryGetCurrentApplication() && xaml::Window::Current()) {
+ if (xaml::TryGetCurrentUwpXamlApplication() && xaml::Window::Current()) {
auto const window = xaml::Window::Current().CoreWindow();
m_windowWidth = window.Bounds().Width;
diff --git a/vnext/Microsoft.ReactNative/Modules/I18nManagerModule.cpp b/vnext/Microsoft.ReactNative/Modules/I18nManagerModule.cpp
index 404c3d3e108..de8c5e01fba 100644
--- a/vnext/Microsoft.ReactNative/Modules/I18nManagerModule.cpp
+++ b/vnext/Microsoft.ReactNative/Modules/I18nManagerModule.cpp
@@ -28,7 +28,7 @@ static const React::ReactPropertyId &ForceRTLPropertyId() noexcept {
}
void I18nManager::InitI18nInfo(const winrt::Microsoft::ReactNative::ReactPropertyBag &propertyBag) noexcept {
- if (xaml::TryGetCurrentApplication() && !IsXamlIsland()) {
+ if (xaml::TryGetCurrentUwpXamlApplication() && !IsXamlIsland()) {
// TODO: Figure out packaged win32 app story for WinUI 3
auto layoutDirection = winrt::Windows::ApplicationModel::Resources::Core::ResourceContext()
.GetForCurrentView()
diff --git a/vnext/Microsoft.ReactNative/Modules/Timing.cpp b/vnext/Microsoft.ReactNative/Modules/Timing.cpp
index 7819f07f74d..083b1f6c542 100644
--- a/vnext/Microsoft.ReactNative/Modules/Timing.cpp
+++ b/vnext/Microsoft.ReactNative/Modules/Timing.cpp
@@ -124,7 +124,7 @@ void TimerRegistry::setTimerManager(std::weak_ptr
void Timing::Initialize(winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept {
m_context = reactContext;
m_properties = reactContext.Properties().Handle();
- m_usePostForRendering = !xaml::TryGetCurrentApplication();
+ m_usePostForRendering = !xaml::TryGetCurrentUwpXamlApplication();
m_uiDispatcher = m_context.UIDispatcher().Handle();
}
@@ -133,7 +133,7 @@ void Timing::InitializeBridgeless(
const winrt::Microsoft::ReactNative::IReactPropertyBag &properties) noexcept {
m_timerRegistry = timerRegistry;
m_properties = properties;
- m_usePostForRendering = !xaml::TryGetCurrentApplication();
+ m_usePostForRendering = !xaml::TryGetCurrentUwpXamlApplication();
m_uiDispatcher = {properties.Get(winrt::Microsoft::ReactNative::ReactDispatcherHelper::UIDispatcherProperty())
.try_as()};
}
diff --git a/vnext/Microsoft.ReactNative/Views/DevMenu.cpp b/vnext/Microsoft.ReactNative/Views/DevMenu.cpp
index d382abe902b..1b8f6a7a4c6 100644
--- a/vnext/Microsoft.ReactNative/Views/DevMenu.cpp
+++ b/vnext/Microsoft.ReactNative/Views/DevMenu.cpp
@@ -397,7 +397,7 @@ std::shared_ptr GetOrCreateDevMenu(Mso::CntPtr std::shared_ptr {
#ifndef CORE_ABI
- if (xaml::TryGetCurrentApplication()) {
+ if (xaml::TryGetCurrentUwpXamlApplication()) {
auto devMenu = std::make_shared(reactContext);
return devMenu;
} else