diff --git a/change/react-native-windows-c93ed00c-bbe5-46ff-b2a7-cacfd804e375.json b/change/react-native-windows-c93ed00c-bbe5-46ff-b2a7-cacfd804e375.json deleted file mode 100644 index 41a6bca6dea..00000000000 --- a/change/react-native-windows-c93ed00c-bbe5-46ff-b2a7-cacfd804e375.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "prerelease", - "comment": "Picker Xaml NativeComponent added to Sample Fabric", - "packageName": "react-native-windows", - "email": "66076509+vineethkuttan@users.noreply.github.com", - "dependentChangeType": "patch" -} \ No newline at end of file diff --git a/packages/sample-app-fabric/App.tsx b/packages/sample-app-fabric/App.tsx index a9abdcfaa67..3ac27a50420 100644 --- a/packages/sample-app-fabric/App.tsx +++ b/packages/sample-app-fabric/App.tsx @@ -5,52 +5,20 @@ * @format */ -import React, {useState} from 'react'; -import { - SafeAreaView, - StatusBar, - useColorScheme, - Text, - View, -} from 'react-native'; +import React from 'react'; +import {SafeAreaView, StatusBar, useColorScheme} from 'react-native'; import {NewAppScreen} from '@react-native/new-app-screen'; -import {PickerXaml} from 'sample-custom-component'; - -const pickerItems = [ - {label: 'JavaScript', value: 'js'}, - {label: 'TypeScript', value: 'ts'}, - {label: 'Python', value: 'py'}, - {label: 'C++', value: 'cpp'}, - {label: 'Rust', value: 'rs'}, -]; function App(): React.JSX.Element { const isDarkMode = useColorScheme() === 'dark'; - const [selectedIndex, setSelectedIndex] = useState(3); // Default to C++ - - const backgroundColor = isDarkMode ? '#1a1a1a' : '#f5f5f5'; - const textColor = isDarkMode ? '#ffffff' : '#000000'; return ( - + - - - Selected: {pickerItems[selectedIndex]?.label} - - { - setSelectedIndex(event.nativeEvent.itemIndex); - }} - /> - ); diff --git a/packages/sample-app-fabric/package.json b/packages/sample-app-fabric/package.json index 994c680907d..5eaca3d7d4a 100644 --- a/packages/sample-app-fabric/package.json +++ b/packages/sample-app-fabric/package.json @@ -18,8 +18,7 @@ "@typescript-eslint/parser": "^7.1.1", "react": "^19.1.1", "react-native": "0.83.0-nightly-20250917-18cb4edfa", - "react-native-windows": "^0.0.0-canary.1031", - "sample-custom-component": "0.0.1" + "react-native-windows": "^0.0.0-canary.1031" }, "devDependencies": { "@babel/core": "^7.25.2", diff --git a/packages/sample-app-fabric/windows/SampleAppFabric.Package/packages.lock.json b/packages/sample-app-fabric/windows/SampleAppFabric.Package/packages.lock.json index 53fe91091b2..896662a49eb 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric.Package/packages.lock.json +++ b/packages/sample-app-fabric/windows/SampleAppFabric.Package/packages.lock.json @@ -185,16 +185,6 @@ "type": "Project", "dependencies": { "Microsoft.JavaScript.Hermes": "[0.0.0-2512.22001-bc3d0ed7, )", - "Microsoft.ReactNative": "[1.0.0, )", - "Microsoft.VCRTForwarders.140": "[1.0.2-rc, )", - "Microsoft.WindowsAppSDK": "[1.8.260209005, )", - "SampleCustomComponent": "[1.0.0, )", - "boost": "[1.83.0, )" - } - }, - "samplecustomcomponent": { - "type": "Project", - "dependencies": { "Microsoft.ReactNative": "[1.0.0, )", "Microsoft.VCRTForwarders.140": "[1.0.2-rc, )", "Microsoft.WindowsAppSDK": "[1.8.260209005, )", diff --git a/packages/sample-app-fabric/windows/SampleAppFabric.sln b/packages/sample-app-fabric/windows/SampleAppFabric.sln index e562e1f033e..3335ca845cd 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric.sln +++ b/packages/sample-app-fabric/windows/SampleAppFabric.sln @@ -33,8 +33,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "..\..\..\vnext\Mso\M EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Include", "..\..\..\vnext\include\Include.vcxitems", "{EF074BA1-2D54-4D49-A28E-5E040B47CD2E}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleCustomComponent", "..\..\..\node_modules\sample-custom-component\windows\SampleCustomComponent\SampleCustomComponent.vcxproj", "{A8DA218C-4CB5-48CB-A9EE-9E6337165D07}" -EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\..\..\vnext\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 @@ -152,18 +150,6 @@ Global {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.ActiveCfg = Release|Win32 {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.Build.0 = Release|Win32 {14B93DC8-FD93-4A6D-81CB-8BC96644501C}.Release|x86.Deploy.0 = Release|Win32 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Debug|x64.ActiveCfg = Debug|x64 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Debug|x64.Build.0 = Debug|x64 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Debug|x86.ActiveCfg = Debug|Win32 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Debug|x86.Build.0 = Debug|Win32 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Debug|ARM64.Build.0 = Debug|ARM64 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Release|x64.ActiveCfg = Release|x64 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Release|x64.Build.0 = Release|x64 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Release|x86.ActiveCfg = Release|Win32 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Release|x86.Build.0 = Release|Win32 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Release|ARM64.ActiveCfg = Release|ARM64 - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07}.Release|ARM64.Build.0 = Release|ARM64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.cpp b/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.cpp index b4f9b7ce9c8..5821cfddc55 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.cpp +++ b/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.cpp @@ -3,16 +3,12 @@ #include "pch.h" #include "AutolinkedNativeModules.g.h" -// Includes from sample-custom-component -#include - namespace winrt::Microsoft::ReactNative { void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders) { - // IReactPackageProviders from sample-custom-component - packageProviders.Append(winrt::SampleCustomComponent::ReactPackageProvider()); + UNREFERENCED_PARAMETER(packageProviders); } } diff --git a/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.targets b/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.targets index 35f260ab39e..6a85ec51cd9 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.targets +++ b/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.targets @@ -2,9 +2,5 @@ - - - {A8DA218C-4CB5-48CB-A9EE-9E6337165D07} - diff --git a/packages/sample-app-fabric/windows/SampleAppFabric/packages.lock.json b/packages/sample-app-fabric/windows/SampleAppFabric/packages.lock.json index 46d5131471c..70f1bea5f6a 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric/packages.lock.json +++ b/packages/sample-app-fabric/windows/SampleAppFabric/packages.lock.json @@ -190,15 +190,6 @@ "Folly": "[1.0.0, )", "boost": "[1.83.0, )" } - }, - "samplecustomcomponent": { - "type": "Project", - "dependencies": { - "Microsoft.ReactNative": "[1.0.0, )", - "Microsoft.VCRTForwarders.140": "[1.0.2-rc, )", - "Microsoft.WindowsAppSDK": "[1.8.260209005, )", - "boost": "[1.83.0, )" - } } }, "native,Version=v0.0/win": { diff --git a/packages/sample-custom-component/src/PickerXamlNativeComponent.ts b/packages/sample-custom-component/src/PickerXamlNativeComponent.ts deleted file mode 100644 index 48d1a7ebc21..00000000000 --- a/packages/sample-custom-component/src/PickerXamlNativeComponent.ts +++ /dev/null @@ -1,43 +0,0 @@ -import {codegenNativeComponent} from 'react-native'; -import type { ViewProps } from 'react-native'; -import type { - Int32, - WithDefault, - BubblingEventHandler, -} from 'react-native/Libraries/Types/CodegenTypes'; - -/** - * Represents a single item in the PickerXaml. - */ -export type PickerXamlItem = Readonly<{ - label: string; - value?: string; -}>; - -/** - * Event payload when the picker selection changes. - */ -export type PickerXamlChangeEvent = Readonly<{ - value: string; - itemIndex: Int32; - text: string; -}>; - -export interface PickerXamlProps extends ViewProps { - /** - * Array of picker items to display. - */ - items: ReadonlyArray; - - /** - * The index of the currently selected item. - */ - selectedIndex?: WithDefault; - - /** - * Callback when selection changes. - */ - onPickerSelect?: BubblingEventHandler; -} - -export default codegenNativeComponent('PickerXaml'); diff --git a/packages/sample-custom-component/src/index.ts b/packages/sample-custom-component/src/index.ts index 58ddfdae77f..eb312b6a4dd 100644 --- a/packages/sample-custom-component/src/index.ts +++ b/packages/sample-custom-component/src/index.ts @@ -9,8 +9,6 @@ import ComboBox from './FabricXamlComboBoxNativeComponent' import CustomAccessibility from './CustomAccessibilityNativeComponent'; -import PickerXaml from './PickerXamlNativeComponent'; - export { CustomAccessibility, DrawingIsland, @@ -18,5 +16,4 @@ export { MovingLightHandle, CalendarView, ComboBox, - PickerXaml, }; diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/PickerXaml.cpp b/packages/sample-custom-component/windows/SampleCustomComponent/PickerXaml.cpp deleted file mode 100644 index dc44560655a..00000000000 --- a/packages/sample-custom-component/windows/SampleCustomComponent/PickerXaml.cpp +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" -#include "PickerXaml.h" - -#if defined(RNW_NEW_ARCH) - -#include "codegen/react/components/SampleCustomComponent/PickerXaml.g.h" - -#include -#include -#include -#include -#include -#include - -namespace winrt::SampleCustomComponent { - -// State to store the measured size -struct PickerXamlStateData : winrt::implements { - PickerXamlStateData(winrt::Windows::Foundation::Size ds) : desiredSize(ds) {} - winrt::Windows::Foundation::Size desiredSize; -}; - -struct PickerXamlComponentView : winrt::implements, - Codegen::BasePickerXaml { - void InitializeContentIsland( - const winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView &islandView) { - // Create ComboBox for picker functionality - m_comboBox = winrt::Microsoft::UI::Xaml::Controls::ComboBox(); - m_comboBox.HorizontalAlignment(winrt::Microsoft::UI::Xaml::HorizontalAlignment::Stretch); - - // For editable ComboBox, trigger selection change always (not just on commit) - m_comboBox.SelectionChangedTrigger(winrt::Microsoft::UI::Xaml::Controls::ComboBoxSelectionChangedTrigger::Always); - - // Listen for size changes on the comboBox - auto weakThis = get_weak(); - m_comboBox.SizeChanged([weakThis](auto const & /*sender*/, auto const & /*args*/) { - if (auto strongThis = weakThis.get()) { - strongThis->RefreshSize(); - } - }); - - // Listen for selection changes - m_selectionChangedRevoker = - m_comboBox.SelectionChanged(winrt::auto_revoke, [weakThis](const auto & /*sender*/, const auto & /*args*/) { - if (auto strongThis = weakThis.get()) { - strongThis->EmitPickerSelectEvent(); - } - }); - - // Listen for text submitted (when user presses Enter in editable mode) - m_textSubmittedRevoker = - m_comboBox.TextSubmitted(winrt::auto_revoke, [weakThis](const auto & /*sender*/, const auto & /*args*/) { - if (auto strongThis = weakThis.get()) { - strongThis->EmitPickerSelectEvent(); - } - }); - - m_island = winrt::Microsoft::UI::Xaml::XamlIsland{}; - m_island.Content(m_comboBox); - islandView.Connect(m_island.ContentIsland()); - m_islandView = winrt::make_weak(islandView); - } - - void UpdateProps( - const winrt::Microsoft::ReactNative::ComponentView &view, - const winrt::com_ptr &newProps, - const winrt::com_ptr &oldProps) noexcept override { - BasePickerXaml::UpdateProps(view, newProps, oldProps); - - // Suspend event handlers during programmatic updates to avoid triggering - // change events. Using RAII ensures handlers are always re-attached. - WithEventsSuspended([&]() { - // Always update items on first render, or when size changes - // (We can't compare items directly as the struct lacks operator==) - if (!oldProps || oldProps->items.size() != newProps->items.size() || m_comboBox.Items().Size() == 0) { - m_comboBox.Items().Clear(); - m_items.clear(); - - for (const auto &item : newProps->items) { - // Store item data - m_items.push_back(item); - - // Add item to ComboBox - auto comboBoxItem = winrt::Microsoft::UI::Xaml::Controls::ComboBoxItem(); - comboBoxItem.Content(winrt::box_value(winrt::to_hstring(item.label))); - m_comboBox.Items().Append(comboBoxItem); - } - } - - // Always update selected index on first render or when changed - if (!oldProps || oldProps->selectedIndex != newProps->selectedIndex || - m_comboBox.SelectedIndex() != newProps->selectedIndex) { - const int32_t selectedIndex = newProps->selectedIndex; - if (selectedIndex >= 0 && selectedIndex < static_cast(m_comboBox.Items().Size())) { - m_comboBox.SelectedIndex(selectedIndex); - } else { - m_comboBox.SelectedIndex(-1); - } - } - }); - - RefreshSize(); - } - - void UpdateState( - const winrt::Microsoft::ReactNative::ComponentView & /*view*/, - const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept override { - m_state = newState; - } - - private: - void RefreshSize() { - m_comboBox.Measure(winrt::Windows::Foundation::Size{ - std::numeric_limits::infinity(), std::numeric_limits::infinity()}); - - const auto desiredSize = m_comboBox.DesiredSize(); - - if (m_state) { - const auto currentState = winrt::get_self(m_state.Data()); - if (desiredSize != currentState->desiredSize) { - m_state.UpdateStateWithMutation([desiredSize](winrt::Windows::Foundation::IInspectable /*data*/) { - return winrt::make(desiredSize); - }); - } - } - } - - void EmitPickerSelectEvent() { - if (auto eventEmitter = this->EventEmitter()) { - const int32_t selectedIndex = m_comboBox.SelectedIndex(); - - Codegen::PickerXamlSpec_onPickerSelect eventArgs; - eventArgs.itemIndex = selectedIndex; - - // Get the selected item value and text if available - if (selectedIndex >= 0 && selectedIndex < static_cast(m_items.size())) { - eventArgs.value = m_items[selectedIndex].value.value_or(""); - eventArgs.text = m_items[selectedIndex].label; - } else { - eventArgs.text = ""; - eventArgs.value = ""; - } - - eventEmitter->onPickerSelect(eventArgs); - } - } - - winrt::weak_ref m_islandView; - winrt::Microsoft::UI::Xaml::XamlIsland m_island{nullptr}; - winrt::Microsoft::UI::Xaml::Controls::ComboBox m_comboBox{nullptr}; - winrt::Microsoft::ReactNative::IComponentState m_state{nullptr}; - std::vector m_items; - winrt::Microsoft::UI::Xaml::Controls::ComboBox::SelectionChanged_revoker m_selectionChangedRevoker; - winrt::Microsoft::UI::Xaml::Controls::ComboBox::TextSubmitted_revoker m_textSubmittedRevoker; - - // RAII helper to temporarily suspend event handlers during programmatic updates. - // This avoids triggering change events when we're setting values from props. - template - void WithEventsSuspended(TAction action) { - m_selectionChangedRevoker.revoke(); - m_textSubmittedRevoker.revoke(); - - action(); - - auto weakThis = get_weak(); - m_selectionChangedRevoker = - m_comboBox.SelectionChanged(winrt::auto_revoke, [weakThis](const auto & /*sender*/, const auto & /*args*/) { - if (auto strongThis = weakThis.get()) { - strongThis->EmitPickerSelectEvent(); - } - }); - m_textSubmittedRevoker = - m_comboBox.TextSubmitted(winrt::auto_revoke, [weakThis](const auto & /*sender*/, const auto & /*args*/) { - if (auto strongThis = weakThis.get()) { - strongThis->EmitPickerSelectEvent(); - } - }); - } -}; - -} // namespace winrt::SampleCustomComponent - -void RegisterPickerXamlComponentView(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) { - winrt::SampleCustomComponent::Codegen::RegisterPickerXamlNativeComponent< - winrt::SampleCustomComponent::PickerXamlComponentView>( - packageBuilder, - [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { - builder.as().XamlSupport(true); - // Use SetContentIslandComponentViewInitializer - builder.SetContentIslandComponentViewInitializer( - [](const winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView &islandView) noexcept { - auto userData = winrt::make_self(); - userData->InitializeContentIsland(islandView); - islandView.UserData(*userData); - }); - // Set up initial state with zero size - builder.as().SetInitialStateDataFactory( - [](const winrt::Microsoft::ReactNative::IComponentProps & /*props*/) noexcept { - return winrt::make( - winrt::Windows::Foundation::Size{0, 0}); - }); - - // Register the measure function - reads from state - builder.as().SetMeasureContentHandler( - [](winrt::Microsoft::ReactNative::ShadowNode const &shadowNode, - winrt::Microsoft::ReactNative::LayoutContext const &, - winrt::Microsoft::ReactNative::LayoutConstraints const &) noexcept { - const auto currentState = - winrt::get_self(shadowNode.StateData()); - - if (currentState && currentState->desiredSize.Width > 0) { - // Return the measured size from state - return currentState->desiredSize; - } - - // Return a default size if we don't have a measurement yet - return winrt::Windows::Foundation::Size{100, 32}; - }); - - // Handle state updates - builder.as().SetUpdateStateHandler( - [](const winrt::Microsoft::ReactNative::ComponentView &view, - const winrt::Microsoft::ReactNative::IComponentState &newState) { - const auto islandView = view.as(); - const auto userData = islandView.UserData().as(); - userData->UpdateState(view, newState); - }); - }); -} - -#endif // defined(RNW_NEW_ARCH) diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/PickerXaml.h b/packages/sample-custom-component/windows/SampleCustomComponent/PickerXaml.h deleted file mode 100644 index dad8f0a44af..00000000000 --- a/packages/sample-custom-component/windows/SampleCustomComponent/PickerXaml.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#if defined(RNW_NEW_ARCH) - -void RegisterPickerXamlComponentView(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder); - -#endif // defined(RNW_NEW_ARCH) diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/ReactPackageProvider.cpp b/packages/sample-custom-component/windows/SampleCustomComponent/ReactPackageProvider.cpp index 4e08df78310..8f19b9be9cf 100644 --- a/packages/sample-custom-component/windows/SampleCustomComponent/ReactPackageProvider.cpp +++ b/packages/sample-custom-component/windows/SampleCustomComponent/ReactPackageProvider.cpp @@ -12,7 +12,6 @@ #include "CustomAccessibility.h" #include "DrawingIsland.h" #include "MovingLight.h" -#include "PickerXaml.h" using namespace winrt::Microsoft::ReactNative; @@ -27,7 +26,6 @@ void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuil RegisterCalendarViewComponentView(packageBuilder); RegisterCustomAccessibilityComponentView(packageBuilder); RegisterComboBoxComponentView(packageBuilder); - RegisterPickerXamlComponentView(packageBuilder); #endif // #ifdef RNW_NEW_ARCH } diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj b/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj index 4f3c7f95748..8462d529796 100644 --- a/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj +++ b/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj @@ -103,7 +103,6 @@ - DrawingIsland.idl @@ -117,7 +116,6 @@ - Create diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/PickerXaml.g.h b/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/PickerXaml.g.h deleted file mode 100644 index 22d5ea891c6..00000000000 --- a/packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/PickerXaml.g.h +++ /dev/null @@ -1,247 +0,0 @@ - -/* - * This file is auto-generated from PickerXamlNativeComponent 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(PickerXamlSpec_PickerXamlProps_items) -struct PickerXamlSpec_PickerXamlProps_items { - REACT_FIELD(label) - std::string label; - - REACT_FIELD(value) - std::optional value; -}; - -REACT_STRUCT(PickerXamlProps) -struct PickerXamlProps : winrt::implements { - PickerXamlProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) - : ViewProps(props) - { - if (cloneFrom) { - auto cloneFromProps = cloneFrom.as(); - items = cloneFromProps->items; - selectedIndex = cloneFromProps->selectedIndex; - } - } - - void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { - winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); - } - - REACT_FIELD(items) - std::vector items; - - REACT_FIELD(selectedIndex) - int32_t selectedIndex{-1}; - - const winrt::Microsoft::ReactNative::ViewProps ViewProps; -}; - -REACT_STRUCT(PickerXamlSpec_onPickerSelect) -struct PickerXamlSpec_onPickerSelect { - REACT_FIELD(value) - std::string value; - - REACT_FIELD(itemIndex) - int32_t itemIndex{}; - - REACT_FIELD(text) - std::string text; -}; - -struct PickerXamlEventEmitter { - PickerXamlEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) - : m_eventEmitter(eventEmitter) {} - - using OnPickerSelect = PickerXamlSpec_onPickerSelect; - - void onPickerSelect(OnPickerSelect &value) const { - m_eventEmitter.DispatchEvent(L"pickerSelect", [&value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { - winrt::Microsoft::ReactNative::WriteValue(writer, value); - }); - } - - private: - winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; -}; - -template -struct BasePickerXaml { - - 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 { - } - - // CreateAutomationPeer will only be called if this method is overridden - virtual winrt::Windows::Foundation::IInspectable CreateAutomationPeer(const winrt::Microsoft::ReactNative::ComponentView & /*view*/, - const winrt::Microsoft::ReactNative::CreateAutomationPeerArgs& /*args*/) noexcept { - return nullptr; - } - - - - 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 RegisterPickerXamlNativeComponent( - winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, - std::function builderCallback) noexcept { - packageBuilder.as().AddViewComponent( - L"PickerXaml", [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_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::FinalizeUpdate != &BasePickerXaml::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_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::UpdateState != &BasePickerXaml::UpdateState) { - builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, - const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { - auto userData = view.UserData().as(); - userData->UpdateState(view, newState); - }); - } - - if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::MountChildComponentView != &BasePickerXaml::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_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::UnmountChildComponentView != &BasePickerXaml::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); - }); - } - - if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::CreateAutomationPeer != &BasePickerXaml::CreateAutomationPeer) { - builder.SetCreateAutomationPeerHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, - const winrt::Microsoft::ReactNative::CreateAutomationPeerArgs& args) noexcept { - auto userData = view.UserData().as(); - return userData->CreateAutomationPeer(view, args); - }); - } - - compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { - auto userData = winrt::make_self(); - if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::Initialize != &BasePickerXaml::Initialize) { - userData->Initialize(view); - } - view.UserData(*userData); - }); - - if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::CreateVisual != &BasePickerXaml::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