From 01e496601c88022fd3b5c48bea4e3675ad61129f Mon Sep 17 00:00:00 2001 From: Jesse Collins Date: Tue, 17 Jun 2025 10:12:13 -0700 Subject: [PATCH 1/4] Checkpoint 1 --- packages/sample-app-fabric/App.tsx | 8 +- packages/sample-app-fabric/b.cmd | 8 + packages/sample-app-fabric/package.json | 5 +- .../windows/SampleAppFabric.sln | 27 +++ .../AutolinkedNativeModules.g.cpp | 6 +- .../AutolinkedNativeModules.g.targets | 4 + .../SampleAppFabric/SampleAppFabric.cpp | 5 + .../windows/SampleAppFabric/pch.h | 1 + packages/xaml-calendar-view/.gitignore | 1 + packages/xaml-calendar-view/NuGet.config | 11 + packages/xaml-calendar-view/babel.config.js | 3 + packages/xaml-calendar-view/jest.config.js | 3 + packages/xaml-calendar-view/just-task.js | 51 +++++ packages/xaml-calendar-view/package.json | 57 +++++ .../xaml-calendar-view/src/CalendarView.tsx | 15 ++ .../src/CalendarViewNativeComponent.ts | 13 ++ packages/xaml-calendar-view/src/index.tsx | 2 + packages/xaml-calendar-view/tsconfig.json | 7 + .../xaml-calendar-view/windows/.gitignore | 41 ++++ .../windows/ExperimentalFeatures.props | 33 +++ .../windows/XamlCalendarView.sln | 43 ++++ .../XamlCalendarView/ReactPackageProvider.cpp | 22 ++ .../XamlCalendarView/ReactPackageProvider.h | 24 +++ .../XamlCalendarView/ReactPackageProvider.idl | 9 + .../XamlCalendarView/XamlCalendarView.cpp | 42 ++++ .../XamlCalendarView/XamlCalendarView.def | 3 + .../XamlCalendarView/XamlCalendarView.h | 37 ++++ .../XamlCalendarView/XamlCalendarView.rc | Bin 0 -> 160 bytes .../XamlCalendarView/XamlCalendarView.vcxproj | 140 ++++++++++++ .../XamlCalendarView.vcxproj.filters | 44 ++++ .../XamlCalendarView/codegen/.clang-format | 2 + .../components/CalendarView/CalendarView.g.h | 200 ++++++++++++++++++ .../windows/XamlCalendarView/pch.cpp | 1 + .../windows/XamlCalendarView/pch.h | 30 +++ .../windows/XamlCalendarView/resource.h | 5 + .../windows/XamlCalendarView/targetver.h | 8 + vnext/ExperimentalFeatures.props | 5 + vnext/Microsoft.ReactNative.Xaml.sln | 40 ++++ vnext/Microsoft.ReactNative.Xaml/App.idl | 19 ++ vnext/Microsoft.ReactNative.Xaml/App.xaml | 6 + .../Microsoft.ReactNative.Xaml.def | 3 + .../Microsoft.ReactNative.Xaml.vcxproj | 177 ++++++++++++++++ ...Microsoft.ReactNative.Xaml.vcxproj.filters | 31 +++ .../PropertySheet.props | 17 ++ .../ReactPackageProvider.cpp | 14 ++ .../ReactPackageProvider.h | 13 ++ .../ReactPackageProvider.idl | 9 + .../XamlApplication.cpp | 78 +++++++ .../XamlApplication.h | 46 ++++ vnext/Microsoft.ReactNative.Xaml/XamlHost.cpp | 70 ++++++ vnext/Microsoft.ReactNative.Xaml/XamlHost.h | 9 + vnext/Microsoft.ReactNative.Xaml/pch.cpp | 1 + vnext/Microsoft.ReactNative.Xaml/pch.h | 27 +++ vnext/Microsoft.ReactNative.Xaml/resource.h | 16 ++ .../ContentIslandComponentView.cpp | 7 +- ...ft.ReactNative.Cpp.ProjectReferences.props | 8 + .../components/rnwcore/ComponentDescriptors.h | 1 + .../components/rnwcore/EventEmitters.cpp | 1 + .../react/components/rnwcore/EventEmitters.h | 7 + .../react/components/rnwcore/Props.cpp | 7 + .../codegen/react/components/rnwcore/Props.h | 10 + .../react/components/rnwcore/ShadowNodes.cpp | 1 + .../react/components/rnwcore/ShadowNodes.h | 11 + .../codegen/react/components/rnwcore/States.h | 12 ++ .../react/components/rnwcore/XamlHost.g.h | 200 ++++++++++++++++++ .../Libraries/Components/Xaml/XamlHost.d.ts | 13 ++ .../Components/Xaml/XamlHost.windows.js | 7 + vnext/src-win/Libraries/platform-types.d.ts | 1 + vnext/src-win/index.windows.js | 4 + .../Xaml/XamlHostNativeComponent.js | 19 ++ 70 files changed, 1794 insertions(+), 7 deletions(-) create mode 100644 packages/sample-app-fabric/b.cmd create mode 100644 packages/xaml-calendar-view/.gitignore create mode 100644 packages/xaml-calendar-view/NuGet.config create mode 100644 packages/xaml-calendar-view/babel.config.js create mode 100644 packages/xaml-calendar-view/jest.config.js create mode 100644 packages/xaml-calendar-view/just-task.js create mode 100644 packages/xaml-calendar-view/package.json create mode 100644 packages/xaml-calendar-view/src/CalendarView.tsx create mode 100644 packages/xaml-calendar-view/src/CalendarViewNativeComponent.ts create mode 100644 packages/xaml-calendar-view/src/index.tsx create mode 100644 packages/xaml-calendar-view/tsconfig.json create mode 100644 packages/xaml-calendar-view/windows/.gitignore create mode 100644 packages/xaml-calendar-view/windows/ExperimentalFeatures.props create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView.sln create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.cpp create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.h create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.idl create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.cpp create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.def create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.h create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.rc create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.vcxproj create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.vcxproj.filters create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/codegen/.clang-format create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/codegen/react/components/CalendarView/CalendarView.g.h create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/pch.cpp create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/pch.h create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/resource.h create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/targetver.h create mode 100644 vnext/Microsoft.ReactNative.Xaml.sln create mode 100644 vnext/Microsoft.ReactNative.Xaml/App.idl create mode 100644 vnext/Microsoft.ReactNative.Xaml/App.xaml create mode 100644 vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.def create mode 100644 vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj create mode 100644 vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj.filters create mode 100644 vnext/Microsoft.ReactNative.Xaml/PropertySheet.props create mode 100644 vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.cpp create mode 100644 vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.h create mode 100644 vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.idl create mode 100644 vnext/Microsoft.ReactNative.Xaml/XamlApplication.cpp create mode 100644 vnext/Microsoft.ReactNative.Xaml/XamlApplication.h create mode 100644 vnext/Microsoft.ReactNative.Xaml/XamlHost.cpp create mode 100644 vnext/Microsoft.ReactNative.Xaml/XamlHost.h create mode 100644 vnext/Microsoft.ReactNative.Xaml/pch.cpp create mode 100644 vnext/Microsoft.ReactNative.Xaml/pch.h create mode 100644 vnext/Microsoft.ReactNative.Xaml/resource.h create mode 100644 vnext/codegen/react/components/rnwcore/XamlHost.g.h create mode 100644 vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts create mode 100644 vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js create mode 100644 vnext/src-win/src/private/specs/components/Xaml/XamlHostNativeComponent.js diff --git a/packages/sample-app-fabric/App.tsx b/packages/sample-app-fabric/App.tsx index 125fe1b98eb..b4cba6dbd1a 100644 --- a/packages/sample-app-fabric/App.tsx +++ b/packages/sample-app-fabric/App.tsx @@ -25,6 +25,8 @@ import { ReloadInstructions, } from 'react-native/Libraries/NewAppScreen'; +import {CalendarView} from 'xaml-calendar-view'; + type SectionProps = PropsWithChildren<{ title: string; }>; @@ -77,9 +79,11 @@ function App(): React.JSX.Element { backgroundColor: isDarkMode ? Colors.black : Colors.white, }}>
- Edit App.tsx to change this - screen and then come back to see your edits. + Edit App.tsx to change this. + I'll try showing a CalendarView here:
+ +
diff --git a/packages/sample-app-fabric/b.cmd b/packages/sample-app-fabric/b.cmd new file mode 100644 index 00000000000..3a60f9a1a14 --- /dev/null +++ b/packages/sample-app-fabric/b.cmd @@ -0,0 +1,8 @@ +setlocal +pushd ..\.. + +call yarn + +popd + +call yarn react-native run-windows --msbuildprops RestoreForceEvaluate=true diff --git a/packages/sample-app-fabric/package.json b/packages/sample-app-fabric/package.json index 93723a1cfd8..6a63218b979 100644 --- a/packages/sample-app-fabric/package.json +++ b/packages/sample-app-fabric/package.json @@ -17,7 +17,8 @@ "@typescript-eslint/parser": "^7.1.1", "react": "^19.0.0", "react-native": "0.79.0-nightly-20250303-cee63397b", - "react-native-windows": "^0.0.0-canary.964" + "react-native-windows": "^0.0.0-canary.964", + "xaml-calendar-view": "" }, "devDependencies": { "@babel/core": "^7.25.2", @@ -48,4 +49,4 @@ "engines": { "node": ">=18" } -} +} \ No newline at end of file diff --git a/packages/sample-app-fabric/windows/SampleAppFabric.sln b/packages/sample-app-fabric/windows/SampleAppFabric.sln index 1eabd0cabef..a5cd2bc11e9 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric.sln +++ b/packages/sample-app-fabric/windows/SampleAppFabric.sln @@ -35,6 +35,8 @@ 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}") = "XamlCalendarView", "..\..\..\node_modules\xaml-calendar-view\windows\XamlCalendarView\XamlCalendarView.vcxproj", "{3501592F-3196-4EE1-B4AA-FE4A5F29063B}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\..\..\vnext\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 @@ -154,6 +156,31 @@ 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 + + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|x64.ActiveCfg = Debug|x64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|x64.Build.0 = Debug|x64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|x86.ActiveCfg = Debug|Win32 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|x86.Build.0 = Debug|Win32 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|ARM64.Build.0 = Debug|ARM64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|x64.ActiveCfg = Release|x64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|x64.Build.0 = Release|x64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|x86.ActiveCfg = Release|Win32 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|x86.Build.0 = Release|Win32 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|ARM64.ActiveCfg = Release|ARM64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|ARM64.Build.0 = Release|ARM64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|x64.ActiveCfg = Debug|x64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|x64.Build.0 = Debug|x64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|x86.ActiveCfg = Debug|Win32 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|x86.Build.0 = Debug|Win32 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|ARM64.Build.0 = Debug|ARM64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|x64.ActiveCfg = Release|x64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|x64.Build.0 = Release|x64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|x86.ActiveCfg = Release|Win32 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|x86.Build.0 = Release|Win32 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|ARM64.ActiveCfg = Release|ARM64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.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 5821cfddc55..bc5c9b03d39 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.cpp +++ b/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.cpp @@ -3,12 +3,16 @@ #include "pch.h" #include "AutolinkedNativeModules.g.h" +// Includes from xaml-calendar-view +#include + namespace winrt::Microsoft::ReactNative { void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders) { - UNREFERENCED_PARAMETER(packageProviders); + // IReactPackageProviders from xaml-calendar-view + packageProviders.Append(winrt::XamlCalendarView::ReactPackageProvider()); } } diff --git a/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.targets b/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.targets index 6a85ec51cd9..0d854874f0b 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.targets +++ b/packages/sample-app-fabric/windows/SampleAppFabric/AutolinkedNativeModules.g.targets @@ -2,5 +2,9 @@ + + + {3501592F-3196-4EE1-B4AA-FE4A5F29063B} + diff --git a/packages/sample-app-fabric/windows/SampleAppFabric/SampleAppFabric.cpp b/packages/sample-app-fabric/windows/SampleAppFabric/SampleAppFabric.cpp index 2aeaae1397e..211ec1b34e3 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric/SampleAppFabric.cpp +++ b/packages/sample-app-fabric/windows/SampleAppFabric/SampleAppFabric.cpp @@ -8,6 +8,8 @@ #include "NativeModules.h" +#include + // A PackageProvider containing any turbo modules you define within this app project struct CompReactPackageProvider : winrt::implements { @@ -39,6 +41,9 @@ _Use_decl_annotations_ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE, PSTR RegisterAutolinkedNativeModulePackages(settings.PackageProviders()); // Register any native modules defined within this app project settings.PackageProviders().Append(winrt::make()); + // TODO: Can we make apps register this automatically? (e.g. with autolinking) + // TODO: But ideally we don't load the M.RN.Xaml.dll at all if we're not using Xaml. + settings.PackageProviders().Append(winrt::Microsoft::ReactNative::Xaml::ReactPackageProvider()); #if BUNDLE // Load the JS bundle from a file (not Metro): diff --git a/packages/sample-app-fabric/windows/SampleAppFabric/pch.h b/packages/sample-app-fabric/windows/SampleAppFabric/pch.h index 364879013f3..0c3c09f6089 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric/pch.h +++ b/packages/sample-app-fabric/windows/SampleAppFabric/pch.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include diff --git a/packages/xaml-calendar-view/.gitignore b/packages/xaml-calendar-view/.gitignore new file mode 100644 index 00000000000..6ec7c452937 --- /dev/null +++ b/packages/xaml-calendar-view/.gitignore @@ -0,0 +1 @@ +lib-commonjs/ diff --git a/packages/xaml-calendar-view/NuGet.config b/packages/xaml-calendar-view/NuGet.config new file mode 100644 index 00000000000..fe459fedd60 --- /dev/null +++ b/packages/xaml-calendar-view/NuGet.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/xaml-calendar-view/babel.config.js b/packages/xaml-calendar-view/babel.config.js new file mode 100644 index 00000000000..bb24878651d --- /dev/null +++ b/packages/xaml-calendar-view/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['module:@rnw-scripts/babel-react-native-config'], +}; diff --git a/packages/xaml-calendar-view/jest.config.js b/packages/xaml-calendar-view/jest.config.js new file mode 100644 index 00000000000..8eb675e9bc6 --- /dev/null +++ b/packages/xaml-calendar-view/jest.config.js @@ -0,0 +1,3 @@ +module.exports = { + preset: 'react-native', +}; diff --git a/packages/xaml-calendar-view/just-task.js b/packages/xaml-calendar-view/just-task.js new file mode 100644 index 00000000000..6627cf0c945 --- /dev/null +++ b/packages/xaml-calendar-view/just-task.js @@ -0,0 +1,51 @@ +/** + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * @format + * @ts-check + */ + +const {task, series} = require('just-scripts'); +const fs = require('fs'); +const glob = require('glob'); +const path = require('path'); + +// Use the shared base configuration +require('@rnw-scripts/just-task'); + +// The TS build process will strip all the types from the NativeComponent spec file. Which means that the codegen babel will not correctly generate the JS view config for the component. +// So here we manually run babel, overwriting the tsc output, so that we ship the generated code. +task('codegenNativeComponents', () => { + const babel = require('@babel/core'); + const matches = glob.sync('src/**/*NativeComponent.ts'); + + matches.forEach(matchedPath => { + const relativePath = path.relative( + path.resolve(process.cwd(), 'src'), + matchedPath, + ); + const code = fs.readFileSync(matchedPath).toString(); + const filename = path.resolve(process.cwd(), matchedPath); + + const res = babel.transformSync(code, { + ast: false, + filename, + cwd: process.cwd(), + sourceRoot: process.cwd(), + root: process.cwd(), + babelrc: true, + }); + + const relativeOutputPath = relativePath.replace(/\.ts$/, '.js'); + + fs.writeFileSync( + path.resolve(process.cwd(), 'lib-commonjs', relativeOutputPath), + res?.code, + ); + }); +}); + +task( + 'buildWithCodegetNativeComponents', + series('build', 'codegenNativeComponents'), +); diff --git a/packages/xaml-calendar-view/package.json b/packages/xaml-calendar-view/package.json new file mode 100644 index 00000000000..28d54e20dfd --- /dev/null +++ b/packages/xaml-calendar-view/package.json @@ -0,0 +1,57 @@ +{ + "name": "xaml-calendar-view", + "version": "1.0.0", + "main": "lib-commonjs/index.js", + "types": "lib-commonjs/index.d.ts", + "license": "MIT", + "private": true, + "scripts": { + "build": "rnw-scripts buildWithCodegetNativeComponents", + "lint": "rnw-scripts lint", + "lint:fix": "rnw-scripts lint:fix" + }, + "codegenConfig": { + "name": "CalendarView", + "type": "all", + "jsSrcsDir": "src", + "windows": { + "generators": "componentsWindows", + "namespace": "winrt::XamlCalendarView::Codegen", + "outputDirectory": "windows/XamlCalendarView/codegen" + } + }, + "dependencies": { + "@types/react": "^19.0.0", + "react": "^19.0.0", + "react-native": "0.79.0-nightly-20250123-d1028885e", + "react-native-windows": "^0.0.0-canary.952" + }, + "devDependencies": { + "@babel/core": "^7.25.2", + "@babel/generator": "^7.25.0", + "@babel/preset-env": "^7.25.3", + "@babel/preset-typescript": "^7.8.3", + "@babel/runtime": "^7.20.0", + "@react-native-community/cli": "15.0.0-alpha.2", + "@react-native/metro-config": "0.79.0-nightly-20250123-d1028885e", + "@rnw-scripts/babel-node-config": "2.3.2", + "@rnw-scripts/babel-react-native-config": "0.0.0", + "@rnw-scripts/eslint-config": "1.2.34", + "@rnw-scripts/just-task": "2.3.51", + "@rnw-scripts/metro-dev-config": "0.0.0", + "@rnw-scripts/ts-config": "2.0.5", + "@rnx-kit/jest-preset": "^0.1.16", + "@types/react": "^19.0.0", + "@typescript-eslint/eslint-plugin": "^7.1.1", + "@typescript-eslint/parser": "^7.1.1", + "babel-jest": "^29.6.3", + "eslint": "^8.19.0", + "glob": "^7.1.6", + "just-scripts": "^1.3.3", + "prettier": "2.8.8", + "typescript": "5.0.4" + }, + "engines": { + "node": ">=18" + } +} diff --git a/packages/xaml-calendar-view/src/CalendarView.tsx b/packages/xaml-calendar-view/src/CalendarView.tsx new file mode 100644 index 00000000000..047aa321312 --- /dev/null +++ b/packages/xaml-calendar-view/src/CalendarView.tsx @@ -0,0 +1,15 @@ + +import * as React from 'react'; +import RawCalendarView from './CalendarViewNativeComponent'; + +import XamlHost from 'react-native-windows/Libraries/Components/Xaml/XamlHost'; + +function CalendarView(props: any) { + return ( + + + + ); +} + +export { CalendarView, RawCalendarView }; diff --git a/packages/xaml-calendar-view/src/CalendarViewNativeComponent.ts b/packages/xaml-calendar-view/src/CalendarViewNativeComponent.ts new file mode 100644 index 00000000000..d7e5608b65d --- /dev/null +++ b/packages/xaml-calendar-view/src/CalendarViewNativeComponent.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + */ + +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import type { ViewProps } from 'react-native'; + +export interface CalendarViewProps extends ViewProps { + label : string; +} + +export default codegenNativeComponent('CalendarView'); diff --git a/packages/xaml-calendar-view/src/index.tsx b/packages/xaml-calendar-view/src/index.tsx new file mode 100644 index 00000000000..5cb606a5706 --- /dev/null +++ b/packages/xaml-calendar-view/src/index.tsx @@ -0,0 +1,2 @@ +import { CalendarView, RawCalendarView} from './CalendarView'; +export { CalendarView, RawCalendarView }; diff --git a/packages/xaml-calendar-view/tsconfig.json b/packages/xaml-calendar-view/tsconfig.json new file mode 100644 index 00000000000..9fe5bc3cf9d --- /dev/null +++ b/packages/xaml-calendar-view/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@rnw-scripts/ts-config", + "include": ["src"], + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/packages/xaml-calendar-view/windows/.gitignore b/packages/xaml-calendar-view/windows/.gitignore new file mode 100644 index 00000000000..5bc72a4416d --- /dev/null +++ b/packages/xaml-calendar-view/windows/.gitignore @@ -0,0 +1,41 @@ +*AppPackages* +*BundleArtifacts* + +#OS junk files +[Tt]humbs.db +*.DS_Store + +#Visual Studio files +*.[Oo]bj +*.user +*.aps +*.pch +*.vspscc +*.vssscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.[Cc]ache +*.ilk +*.log +*.lib +*.sbr +*.sdf +*.opensdf +*.opendb +*.unsuccessfulbuild +ipch/ +[Oo]bj/ +[Bb]in +[Dd]ebug*/ +[Rr]elease*/ +Ankh.NoLoad +.vs/ +# Visual C++ cache files + +#Files generated by the VS build +**/Generated Files/** diff --git a/packages/xaml-calendar-view/windows/ExperimentalFeatures.props b/packages/xaml-calendar-view/windows/ExperimentalFeatures.props new file mode 100644 index 00000000000..3153babecb8 --- /dev/null +++ b/packages/xaml-calendar-view/windows/ExperimentalFeatures.props @@ -0,0 +1,33 @@ + + + + + + true + + + false + + true + + + diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView.sln b/packages/xaml-calendar-view/windows/XamlCalendarView.sln new file mode 100644 index 00000000000..cb7fc4ee0b2 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32929.385 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XamlCalendarView", "XamlCalendarView\XamlCalendarView.vcxproj", "{3501592F-3196-4EE1-B4AA-FE4A5F29063B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Debug|ARM64 = Debug|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + Release|ARM64 = Release|ARM64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|x64.ActiveCfg = Debug|x64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|x64.Build.0 = Debug|x64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|x64.Deploy.0 = Debug|x64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|x86.ActiveCfg = Debug|Win32 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|x86.Build.0 = Debug|Win32 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|x86.Deploy.0 = Debug|Win32 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|ARM64.Build.0 = Debug|ARM64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|x64.ActiveCfg = Release|x64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|x64.Build.0 = Release|x64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|x64.Deploy.0 = Release|x64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|x86.ActiveCfg = Release|Win32 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|x86.Build.0 = Release|Win32 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|x86.Deploy.0 = Release|Win32 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|ARM64.ActiveCfg = Release|ARM64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|ARM64.Build.0 = Release|ARM64 + {3501592F-3196-4EE1-B4AA-FE4A5F29063B}.Release|ARM64.Deploy.0 = Release|ARM64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D43FAD39-F619-437D-BB40-04A3982ACB6A} + EndGlobalSection +EndGlobal diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.cpp b/packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.cpp new file mode 100644 index 00000000000..e2cff280d6c --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.cpp @@ -0,0 +1,22 @@ +#include "pch.h" + +#include "ReactPackageProvider.h" +#if __has_include("ReactPackageProvider.g.cpp") +#include "ReactPackageProvider.g.cpp" +#endif + +#include "XamlCalendarView.h" + +using namespace winrt::Microsoft::ReactNative; + +namespace winrt::XamlCalendarView::implementation +{ + +void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept +{ + AddAttributedModules(packageBuilder, true); + RegisterCalendarViewNativeComponent(packageBuilder); + //settings.PackageProviders().Append(winrt::Microsoft::ReactNative::Xaml::ReactPackageProvider()); +} + +} // namespace winrt::XamlCalendarView::implementation diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.h b/packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.h new file mode 100644 index 00000000000..7baeecd516c --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.h @@ -0,0 +1,24 @@ +#pragma once + +#include "ReactPackageProvider.g.h" + +using namespace winrt::Microsoft::ReactNative; + +namespace winrt::XamlCalendarView::implementation +{ + +struct ReactPackageProvider : ReactPackageProviderT +{ + ReactPackageProvider() = default; + + void CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept; +}; + +} // namespace winrt::XamlCalendarView::implementation + +namespace winrt::XamlCalendarView::factory_implementation +{ + +struct ReactPackageProvider : ReactPackageProviderT {}; + +} // namespace winrt::XamlCalendarView::factory_implementation diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.idl b/packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.idl new file mode 100644 index 00000000000..ce11fd77d80 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/ReactPackageProvider.idl @@ -0,0 +1,9 @@ +namespace XamlCalendarView +{ + [webhosthidden] + [default_interface] + runtimeclass ReactPackageProvider : Microsoft.ReactNative.IReactPackageProvider + { + ReactPackageProvider(); + }; +} diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.cpp b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.cpp new file mode 100644 index 00000000000..2d84d2719f4 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.cpp @@ -0,0 +1,42 @@ +#include "pch.h" + +#include "XamlCalendarView.h" + +#include +#include + +namespace winrt::XamlCalendarView +{ + +struct CalendarView : public winrt::implements, + Codegen::BaseCalendarView { + + winrt::Microsoft::UI::Xaml::UIElement GetXamlElement() { + if (m_calendarView == nullptr) { + m_calendarView = winrt::Microsoft::UI::Xaml::Controls::CalendarView(); + } + return m_calendarView; + } + + private: + winrt::Microsoft::UI::Xaml::Controls::CalendarView m_calendarView{ nullptr }; +}; + + +// See https://microsoft.github.io/react-native-windows/docs/native-modules for details on writing native modules + +void XamlCalendarView::Initialize(React::ReactContext const &reactContext) noexcept { + m_context = reactContext; +} + +double XamlCalendarView::multiply(double a, double b) noexcept { + return a * b; +} + +void RegisterCalendarViewNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept { + Codegen::RegisterCalendarViewNativeComponent(packageBuilder, {}); +} + + +} // namespace winrt::XamlCalendarView diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.def b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.def new file mode 100644 index 00000000000..24e7c1235c3 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.h b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.h new file mode 100644 index 00000000000..2f57b16c4ff --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.h @@ -0,0 +1,37 @@ +#pragma once + +#include "pch.h" +#include "resource.h" + +#if __has_include("codegen/NativeXamlCalendarViewDataTypes.g.h") + #include "codegen/NativeXamlCalendarViewDataTypes.g.h" +#endif + +#include "codegen/react/components/CalendarView/CalendarView.g.h" + +#include "NativeModules.h" + +namespace winrt::XamlCalendarView +{ + +REACT_MODULE(XamlCalendarView) +struct XamlCalendarView +{ + //using ModuleSpec = XamlCalendarViewCodegen::XamlCalendarViewSpec; + + REACT_INIT(Initialize) + void Initialize(React::ReactContext const &reactContext) noexcept; + + REACT_SYNC_METHOD(multiply) + double multiply(double a, double b) noexcept; + +private: + React::ReactContext m_context; +}; + +void RegisterCalendarViewNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept; + +} // namespace winrt::XamlCalendarView + + diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.rc b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.rc new file mode 100644 index 0000000000000000000000000000000000000000..3212c105fce3ed3e784a1f88d04cd4b26a0d7f4f GIT binary patch literal 160 zcmZXNK?;LF3`O6%&^rveEI5bgx?A_6wiU#d(Ye0ubG8z~PhNhK-yVqs9!&HkKCI@G zP1ed*G99zsotqJOF|wFRzNv#OsmETn>aBy_ac$zOr{T)QFR^GXU7XIkhvKbH`wefZ G;{F4P;Ty#O literal 0 HcmV?d00001 diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.vcxproj b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.vcxproj new file mode 100644 index 00000000000..0d6a8c26676 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.vcxproj @@ -0,0 +1,140 @@ + + + + + + true + true + {3501592F-3196-4EE1-B4AA-FE4A5F29063B} + XamlCalendarView + Win32Proj + XamlCalendarView + 10.0 + en-US + 17.0 + false + + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ + false + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + DynamicLibrary + Unicode + v143 + false + + + true + + + false + true + + + + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + Level4 + true + %(AdditionalOptions) /bigobj + 4453;28204 + _WINRT_DLL;%(PreprocessorDefinitions) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + stdcpp20 + + + shell32.lib;user32.lib;windowsapp.lib;%(AdditionalDependenices) + Console + true + XamlCalendarView.def + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + + + ReactPackageProvider.idl + + + + + + + + + Create + + + ReactPackageProvider.idl + + + + + + + + + + + + + + + + + + This project references targets in your node_modules\react-native-windows folder. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.vcxproj.filters b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.vcxproj.filters new file mode 100644 index 00000000000..c14f7bdb9af --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.vcxproj.filters @@ -0,0 +1,44 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/codegen/.clang-format b/packages/xaml-calendar-view/windows/XamlCalendarView/codegen/.clang-format new file mode 100644 index 00000000000..a43d914ec38 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/codegen/.clang-format @@ -0,0 +1,2 @@ +DisableFormat: true +SortIncludes: false \ No newline at end of file diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/codegen/react/components/CalendarView/CalendarView.g.h b/packages/xaml-calendar-view/windows/XamlCalendarView/codegen/react/components/CalendarView/CalendarView.g.h new file mode 100644 index 00000000000..a8c748f7ca6 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/codegen/react/components/CalendarView/CalendarView.g.h @@ -0,0 +1,200 @@ + +/* + * 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::XamlCalendarView::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; +}; + +struct CalendarViewEventEmitter { + CalendarViewEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + 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_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&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_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&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->UpdateState(view, newState); + }); + } + + if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&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_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&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_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::Initialize != &BaseCalendarView::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&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::XamlCalendarView::Codegen + +#endif // #ifdef RNW_NEW_ARCH diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/pch.cpp b/packages/xaml-calendar-view/windows/XamlCalendarView/pch.cpp new file mode 100644 index 00000000000..1d9f38c57d6 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/pch.h b/packages/xaml-calendar-view/windows/XamlCalendarView/pch.h new file mode 100644 index 00000000000..61d356df65a --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/pch.h @@ -0,0 +1,30 @@ +// pch.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#define NOMINMAX 1 +#define WIN32_LEAN_AND_MEAN 1 +#define WINRT_LEAN_AND_MEAN 1 + +// Windows Header Files +#include +#undef GetCurrentTime +#include + +// WinRT Header Files +#include +#include +#include + +// C RunTime Header Files +#include +#include +#include +#include + +// Reference additional headers your project requires here diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/resource.h b/packages/xaml-calendar-view/windows/XamlCalendarView/resource.h new file mode 100644 index 00000000000..c8bbf48db31 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/resource.h @@ -0,0 +1,5 @@ +// +// Microsoft Visual C++ generated include file. +// Used by XamlCalendarView.rc + +#pragma once diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/targetver.h b/packages/xaml-calendar-view/windows/XamlCalendarView/targetver.h new file mode 100644 index 00000000000..87c0086de75 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/vnext/ExperimentalFeatures.props b/vnext/ExperimentalFeatures.props index f305876cfb9..cc658d2cced 100644 --- a/vnext/ExperimentalFeatures.props +++ b/vnext/ExperimentalFeatures.props @@ -9,6 +9,11 @@ true true + + true + true + true + false diff --git a/vnext/Microsoft.ReactNative.Xaml.sln b/vnext/Microsoft.ReactNative.Xaml.sln new file mode 100644 index 00000000000..9e3cae992db --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml.sln @@ -0,0 +1,40 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35913.81 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Xaml", "Microsoft.ReactNative.Xaml\Microsoft.ReactNative.Xaml.vcxproj", "{E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|ARM64.Build.0 = Debug|ARM64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|x64.ActiveCfg = Debug|x64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|x64.Build.0 = Debug|x64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|x86.ActiveCfg = Debug|Win32 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Debug|x86.Build.0 = Debug|Win32 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|ARM64.ActiveCfg = Release|ARM64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|ARM64.Build.0 = Release|ARM64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|x64.ActiveCfg = Release|x64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|x64.Build.0 = Release|x64 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|x86.ActiveCfg = Release|Win32 + {E5D1B5D2-0E6A-4011-8BCD-08968256DCBD}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3B36CAF0-BCD9-42C7-B311-05FDDCCEC9D4} + EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{e5d1b5d2-0e6a-4011-8bcd-08968256dcbd}*SharedItemsImports = 4 + EndGlobalSection +EndGlobal diff --git a/vnext/Microsoft.ReactNative.Xaml/App.idl b/vnext/Microsoft.ReactNative.Xaml/App.idl new file mode 100644 index 00000000000..1e889e85a2b --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/App.idl @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.ReactNative.Xaml +{ + [webhosthidden][default_interface] runtimeclass XamlApplication : Microsoft.UI.Xaml.Application, + Microsoft.UI.Xaml.Markup.IXamlMetadataProvider + { + XamlApplication(); + + static void EnsureCreated(); + + static XamlApplication Current { + get; + }; + + void AddMetadataProvider(Microsoft.UI.Xaml.Markup.IXamlMetadataProvider otherProvider); + } +} diff --git a/vnext/Microsoft.ReactNative.Xaml/App.xaml b/vnext/Microsoft.ReactNative.Xaml/App.xaml new file mode 100644 index 00000000000..49d60714075 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/App.xaml @@ -0,0 +1,6 @@ + + diff --git a/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.def b/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.def new file mode 100644 index 00000000000..24e7c1235c3 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj b/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj new file mode 100644 index 00000000000..b12f7a1e40b --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj @@ -0,0 +1,177 @@ + + + + + true + true + true + {e5d1b5d2-0e6a-4011-8bcd-08968256dcbd} + Microsoft.ReactNative.Xaml + Microsoft.ReactNative.Xaml + en-US + 16.0 + false + Windows Store + 10.0 + 10.0.22621.0 + 10.0.17763.0 + true + true + + + + + + + + Debug + Win32 + + + Debug + x64 + + + Debug + ARM64 + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + DynamicLibrary + v143 + Unicode + false + true + + + true + true + + + false + true + false + + + + + + + + + + + + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + Level4 + %(AdditionalOptions) /bigobj + _WINRT_DLL;%(PreprocessorDefinitions) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + true + Microsoft.ReactNative.Xaml.def + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + true + true + + + + + + ReactPackageProvider.idl + + + + + Create + + + ReactPackageProvider.idl + + + + + + + + + + + Code + + + + + + + + + + + + {fca38f3c-7c73-4c47-be4e-32f77fa8538d} + + + {a990658c-ce31-4bcc-976f-0fc6b1af693d} + + + {a9d95a91-4db7-4f72-beb6-fe8a5c89bfbd} + + + {f7d32bd0-2749-483e-9a0d-1635ef7e3136} + + + + + + + + + + + + + + + diff --git a/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj.filters b/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj.filters new file mode 100644 index 00000000000..24eec322ed6 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj.filters @@ -0,0 +1,31 @@ + + + + + accd3aa8-1ba0-4223-9bbe-0c431709210b + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + {926ab91d-31b4-48c3-b9a4-e681349f27f0} + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative.Xaml/PropertySheet.props b/vnext/Microsoft.ReactNative.Xaml/PropertySheet.props new file mode 100644 index 00000000000..5b718b12519 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/PropertySheet.props @@ -0,0 +1,17 @@ + + + + + + normal + + + + + + $(CppWinRTVerbosity) + + + \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.cpp b/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.cpp new file mode 100644 index 00000000000..e020bc2191e --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.cpp @@ -0,0 +1,14 @@ +#include "pch.h" +#include "ReactPackageProvider.h" +#include "ReactPackageProvider.g.cpp" +#include "ModuleRegistration.h" + +#include "XamlHost.h" + +namespace winrt::Microsoft::ReactNative::Xaml::implementation { +void ReactPackageProvider::CreatePackage(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) { + AddAttributedModules(packageBuilder, true); + + RegisterXamlHostComponentView(packageBuilder); +} +} // namespace winrt::Microsoft::ReactNative::Xaml::implementation diff --git a/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.h b/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.h new file mode 100644 index 00000000000..bf39097efbb --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.h @@ -0,0 +1,13 @@ +#pragma once +#include "ReactPackageProvider.g.h" + +namespace winrt::Microsoft::ReactNative::Xaml::implementation { +struct ReactPackageProvider : ReactPackageProviderT { + ReactPackageProvider() = default; + + void CreatePackage(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder); +}; +} // namespace winrt::Microsoft::ReactNative::Xaml::implementation +namespace winrt::Microsoft::ReactNative::Xaml::factory_implementation { +struct ReactPackageProvider : ReactPackageProviderT {}; +} // namespace winrt::Microsoft::ReactNative::Xaml::factory_implementation diff --git a/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.idl b/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.idl new file mode 100644 index 00000000000..f8f7acbe260 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.idl @@ -0,0 +1,9 @@ +namespace Microsoft.ReactNative.Xaml +{ + [webhosthidden] + [default_interface] + runtimeclass ReactPackageProvider : Microsoft.ReactNative.IReactPackageProvider + { + ReactPackageProvider(); + }; +} diff --git a/vnext/Microsoft.ReactNative.Xaml/XamlApplication.cpp b/vnext/Microsoft.ReactNative.Xaml/XamlApplication.cpp new file mode 100644 index 00000000000..1203a92acbe --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/XamlApplication.cpp @@ -0,0 +1,78 @@ +#include "pch.h" + +#include "XamlApplication.h" + +#include "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; +} + +IXamlType XamlApplication::GetXamlType(TypeName const &type) { + for (auto &&provider : m_providers) { + if (auto result = provider.GetXamlType(type)) { + return result; + } + } + return nullptr; +} + +IXamlType XamlApplication::GetXamlType(::winrt::hstring const &fullName) { + for (auto &&provider : m_providers) { + if (auto result = provider.GetXamlType(fullName)) { + return result; + } + } + + return nullptr; +} + +::winrt::com_array<::winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition> XamlApplication::GetXmlnsDefinitions() { + std::vector<::winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition> allDefinitions; + for (const auto &provider : m_providers) { + auto definitionsCurrentProvider = provider.GetXmlnsDefinitions(); + for (const auto &definition : definitionsCurrentProvider) { + allDefinitions.insert(allDefinitions.begin(), definition); + } + } + return winrt::com_array<::winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition>( + allDefinitions.begin(), allDefinitions.end()); +} + +void XamlApplication::AddMetadataProvider( + winrt::Microsoft::UI::Xaml::Markup::IXamlMetadataProvider const &otherProvider) { + m_providers.push_back(otherProvider); +} + +winrt::Microsoft::ReactNative::Xaml::XamlApplication XamlApplication::s_current{nullptr}; + +} // namespace winrt::Microsoft::ReactNative::Xaml::implementation diff --git a/vnext/Microsoft.ReactNative.Xaml/XamlApplication.h b/vnext/Microsoft.ReactNative.Xaml/XamlApplication.h new file mode 100644 index 00000000000..4018e1f3a04 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/XamlApplication.h @@ -0,0 +1,46 @@ +#pragma once +#include "XamlApplication.g.h" + +#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 { + using IXamlType = ::winrt::Microsoft::UI::Xaml::Markup::IXamlType; + + XamlApplication(); + ~XamlApplication(); + + static void EnsureCreated() { + if (Current() == nullptr) { + // Create this type + winrt::make(); + } + } + + static winrt::Microsoft::ReactNative::Xaml::XamlApplication Current() { + return s_current; + } + + IXamlType GetXamlType(::winrt::Windows::UI::Xaml::Interop::TypeName const &type); + + IXamlType GetXamlType(::winrt::hstring const &fullName); + + ::winrt::com_array<::winrt::Microsoft::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions(); + + void AddMetadataProvider(winrt::Microsoft::UI::Xaml::Markup::IXamlMetadataProvider const &otherProvider); + + 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.Xaml/XamlHost.cpp b/vnext/Microsoft.ReactNative.Xaml/XamlHost.cpp new file mode 100644 index 00000000000..d47d6c6b7e2 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/XamlHost.cpp @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" + +#include "FabricXamlControl.h" +#include "XamlApplication.h" +#include "XamlHost.h" + +#if defined(RNW_NEW_ARCH) + +#include "..\codegen\react\components\rnwcore\XamlHost.g.h" + +namespace winrt::Microsoft::ReactNative::Xaml { + +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{}; + + auto grid = winrt::Microsoft::UI::Xaml::Controls::Grid{}; + auto button = winrt::Microsoft::UI::Xaml::Controls::Button{}; + button.Content(winrt::box_value(L"(This is placeholder content for the XamlHost.)")); + grid.Children().Append(button); + m_xamlIsland.Content(grid); + + // m_xamlIsland.Content(m_XamlHost); + 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::Xaml + +void RegisterXamlHostComponentView(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) { + ::Microsoft::ReactNativeSpecs::RegisterXamlHostNativeComponent< + winrt::Microsoft::ReactNative::Xaml::XamlHostComponentView>( + 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.Xaml/XamlHost.h b/vnext/Microsoft.ReactNative.Xaml/XamlHost.h new file mode 100644 index 00000000000..50717a3f53e --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/XamlHost.h @@ -0,0 +1,9 @@ +#pragma once + +#if defined(RNW_NEW_ARCH) + +void RegisterXamlHostComponentView(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder); + +void RegisterXamlControl(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder); + +#endif // defined(RNW_NEW_ARCH) && defined(USE_EXPERIMENTAL_WINUI3) diff --git a/vnext/Microsoft.ReactNative.Xaml/pch.cpp b/vnext/Microsoft.ReactNative.Xaml/pch.cpp new file mode 100644 index 00000000000..1d9f38c57d6 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/vnext/Microsoft.ReactNative.Xaml/pch.h b/vnext/Microsoft.ReactNative.Xaml/pch.h new file mode 100644 index 00000000000..cccf869f820 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/pch.h @@ -0,0 +1,27 @@ +#pragma once +#include +#include +#include +#include + +// Undefine GetCurrentTime macro to prevent +// conflict with Storyboard::GetCurrentTime +#undef GetCurrentTime + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include diff --git a/vnext/Microsoft.ReactNative.Xaml/resource.h b/vnext/Microsoft.ReactNative.Xaml/resource.h new file mode 100644 index 00000000000..5c610888ab7 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Resource.rc +// +#define IDD_DIALOG1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp index 57aa7d14656..b3a26693c66 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp @@ -178,14 +178,17 @@ ContentIslandComponentView::~ContentIslandComponentView() noexcept { void ContentIslandComponentView::MountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept { - assert(false); + // I assume this is here b/c it doesn't make sense for a Island CV to have children. + // XamlHost does have children, but the children will represent Xaml elements and + // don't participate direction in RN's rendering. + // assert(false); base_type::MountChildComponentView(childComponentView, index); } void ContentIslandComponentView::UnmountChildComponentView( const winrt::Microsoft::ReactNative::ComponentView &childComponentView, uint32_t index) noexcept { - assert(false); + // assert(false); base_type::UnmountChildComponentView(childComponentView, index); } diff --git a/vnext/PropertySheets/External/Microsoft.ReactNative.Cpp.ProjectReferences.props b/vnext/PropertySheets/External/Microsoft.ReactNative.Cpp.ProjectReferences.props index 1f58b7e950a..b255f226e74 100644 --- a/vnext/PropertySheets/External/Microsoft.ReactNative.Cpp.ProjectReferences.props +++ b/vnext/PropertySheets/External/Microsoft.ReactNative.Cpp.ProjectReferences.props @@ -18,5 +18,13 @@ Microsoft.ReactNative false + + + + {e5d1b5d2-0e6a-4011-8bcd-08968256dcbd} + Microsoft.ReactNative.Xaml + false + + diff --git a/vnext/codegen/react/components/rnwcore/ComponentDescriptors.h b/vnext/codegen/react/components/rnwcore/ComponentDescriptors.h index 45b7b5ea904..f3d7509b0e9 100644 --- a/vnext/codegen/react/components/rnwcore/ComponentDescriptors.h +++ b/vnext/codegen/react/components/rnwcore/ComponentDescriptors.h @@ -23,6 +23,7 @@ using DebuggingOverlayComponentDescriptor = ConcreteComponentDescriptor; using SwitchComponentDescriptor = ConcreteComponentDescriptor; using UnimplementedNativeViewComponentDescriptor = ConcreteComponentDescriptor; +using XamlHostComponentDescriptor = ConcreteComponentDescriptor; void rnwcore_registerComponentDescriptorsFromCodegen( std::shared_ptr registry); diff --git a/vnext/codegen/react/components/rnwcore/EventEmitters.cpp b/vnext/codegen/react/components/rnwcore/EventEmitters.cpp index adcd150d680..b78a6087acf 100644 --- a/vnext/codegen/react/components/rnwcore/EventEmitters.cpp +++ b/vnext/codegen/react/components/rnwcore/EventEmitters.cpp @@ -129,4 +129,5 @@ void SwitchEventEmitter::onChange(OnChange $event) const { } + } // namespace facebook::react diff --git a/vnext/codegen/react/components/rnwcore/EventEmitters.h b/vnext/codegen/react/components/rnwcore/EventEmitters.h index 0c3bce4a218..ccac8315736 100644 --- a/vnext/codegen/react/components/rnwcore/EventEmitters.h +++ b/vnext/codegen/react/components/rnwcore/EventEmitters.h @@ -165,5 +165,12 @@ class UnimplementedNativeViewEventEmitter : public ViewEventEmitter { +}; +class XamlHostEventEmitter : public ViewEventEmitter { + public: + using ViewEventEmitter::ViewEventEmitter; + + + }; } // namespace facebook::react diff --git a/vnext/codegen/react/components/rnwcore/Props.cpp b/vnext/codegen/react/components/rnwcore/Props.cpp index 3d33bfb0980..9e1ca41bd42 100644 --- a/vnext/codegen/react/components/rnwcore/Props.cpp +++ b/vnext/codegen/react/components/rnwcore/Props.cpp @@ -153,5 +153,12 @@ UnimplementedNativeViewProps::UnimplementedNativeViewProps( name(convertRawProp(context, rawProps, "name", sourceProps.name, {""})) {} +XamlHostProps::XamlHostProps( + const PropsParserContext &context, + const XamlHostProps &sourceProps, + const RawProps &rawProps): ViewProps(context, sourceProps, rawProps), + + label(convertRawProp(context, rawProps, "label", sourceProps.label, {})) + {} } // namespace facebook::react diff --git a/vnext/codegen/react/components/rnwcore/Props.h b/vnext/codegen/react/components/rnwcore/Props.h index 397bc1706cb..5805acbd7d5 100644 --- a/vnext/codegen/react/components/rnwcore/Props.h +++ b/vnext/codegen/react/components/rnwcore/Props.h @@ -395,4 +395,14 @@ class UnimplementedNativeViewProps final : public ViewProps { std::string name{""}; }; +class XamlHostProps final : public ViewProps { + public: + XamlHostProps() = default; + XamlHostProps(const PropsParserContext& context, const XamlHostProps &sourceProps, const RawProps &rawProps); + +#pragma mark - Props + + std::string label{}; +}; + } // namespace facebook::react diff --git a/vnext/codegen/react/components/rnwcore/ShadowNodes.cpp b/vnext/codegen/react/components/rnwcore/ShadowNodes.cpp index dccefb1d478..627e9a2d3fe 100644 --- a/vnext/codegen/react/components/rnwcore/ShadowNodes.cpp +++ b/vnext/codegen/react/components/rnwcore/ShadowNodes.cpp @@ -19,5 +19,6 @@ extern const char DebuggingOverlayComponentName[] = "DebuggingOverlay"; extern const char PullToRefreshViewComponentName[] = "PullToRefreshView"; extern const char SwitchComponentName[] = "Switch"; extern const char UnimplementedNativeViewComponentName[] = "UnimplementedNativeView"; +extern const char XamlHostComponentName[] = "XamlHost"; } // namespace facebook::react diff --git a/vnext/codegen/react/components/rnwcore/ShadowNodes.h b/vnext/codegen/react/components/rnwcore/ShadowNodes.h index 2c7c94720cf..9b45530d5ad 100644 --- a/vnext/codegen/react/components/rnwcore/ShadowNodes.h +++ b/vnext/codegen/react/components/rnwcore/ShadowNodes.h @@ -95,4 +95,15 @@ using UnimplementedNativeViewShadowNode = ConcreteViewShadowNode< UnimplementedNativeViewEventEmitter, UnimplementedNativeViewState>; +JSI_EXPORT extern const char XamlHostComponentName[]; + +/* + * `ShadowNode` for component. + */ +using XamlHostShadowNode = ConcreteViewShadowNode< + XamlHostComponentName, + XamlHostProps, + XamlHostEventEmitter, + XamlHostState>; + } // namespace facebook::react diff --git a/vnext/codegen/react/components/rnwcore/States.h b/vnext/codegen/react/components/rnwcore/States.h index df8b9e54057..efc143b39cc 100644 --- a/vnext/codegen/react/components/rnwcore/States.h +++ b/vnext/codegen/react/components/rnwcore/States.h @@ -98,4 +98,16 @@ class UnimplementedNativeViewState { #endif }; +class XamlHostState { +public: + XamlHostState() = default; + +#ifdef ANDROID + XamlHostState(XamlHostState const &previousState, folly::dynamic data){}; + folly::dynamic getDynamic() const { + return {}; + }; +#endif +}; + } // namespace facebook::react \ No newline at end of file diff --git a/vnext/codegen/react/components/rnwcore/XamlHost.g.h b/vnext/codegen/react/components/rnwcore/XamlHost.g.h new file mode 100644 index 00000000000..26bd059c3c3 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/XamlHost.g.h @@ -0,0 +1,200 @@ + +/* + * This file is auto-generated from XamlHostNativeComponent 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 Microsoft::ReactNativeSpecs { + +REACT_STRUCT(XamlHostProps) +struct XamlHostProps : winrt::implements { + XamlHostProps(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::optional label; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +struct XamlHostEventEmitter { + XamlHostEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseXamlHost { + + 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 RegisterXamlHostNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"XamlHost", [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 != &BaseXamlHost::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 != &BaseXamlHost::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 != &BaseXamlHost::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 != &BaseXamlHost::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_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::Initialize != &BaseXamlHost::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::CreateVisual != &BaseXamlHost::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 Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH 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..f3b49f6bc78 --- /dev/null +++ b/vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js @@ -0,0 +1,7 @@ +/** + * @format + * @flow + */ + +import XamlHost from '../../../src/private/specs/components/Xaml/XamlHostNativeComponent'; +export default XamlHost; diff --git a/vnext/src-win/Libraries/platform-types.d.ts b/vnext/src-win/Libraries/platform-types.d.ts index c201a5c88c1..6d379587659 100644 --- a/vnext/src-win/Libraries/platform-types.d.ts +++ b/vnext/src-win/Libraries/platform-types.d.ts @@ -17,3 +17,4 @@ export const ViewWindows = View; import type {View} from './Components/View/View'; export type ViewWindows = View; export * from './AppTheme/AppThemeTypes'; +export * from '../src/private/specs/components/Xaml/XamlHostTypes'; diff --git a/vnext/src-win/index.windows.js b/vnext/src-win/index.windows.js index 43bcc600df9..9af8e7439a2 100644 --- a/vnext/src-win/index.windows.js +++ b/vnext/src-win/index.windows.js @@ -42,6 +42,7 @@ import typeof SafeAreaView from './Libraries/Components/SafeAreaView/SafeAreaVie import typeof ScrollView from './Libraries/Components/ScrollView/ScrollView'; import typeof StatusBar from './Libraries/Components/StatusBar/StatusBar'; import typeof Switch from './Libraries/Components/Switch/Switch'; +import typeof XamlHost from './Libraries/Components/Xaml/XamlHost'; import typeof InputAccessoryView from './Libraries/Components/TextInput/InputAccessoryView'; import typeof TextInput from './Libraries/Components/TextInput/TextInput'; import typeof ToastAndroid from './Libraries/Components/ToastAndroid/ToastAndroid'; @@ -186,6 +187,9 @@ module.exports = { get Switch(): Switch { return require('./Libraries/Components/Switch/Switch').default; }, + get XamlHost(): XamlHost { + return require('./Libraries/Components/Xaml/XamlHost').default; + }, get Text(): Text { return require('./Libraries/Text/Text').default; }, diff --git a/vnext/src-win/src/private/specs/components/Xaml/XamlHostNativeComponent.js b/vnext/src-win/src/private/specs/components/Xaml/XamlHostNativeComponent.js new file mode 100644 index 00000000000..4cf39730380 --- /dev/null +++ b/vnext/src-win/src/private/specs/components/Xaml/XamlHostNativeComponent.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * @format + * @flow + */ + +'use strict'; + +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; + +type XamlHostProps = $ReadOnly<{| + ...ViewProps, + + // Props + label?: string, +|}>; + +export default codegenNativeComponent('XamlHost'); From 36d311647c478a273448c81065ec5c4a27be5347 Mon Sep 17 00:00:00 2001 From: Jesse Collins Date: Tue, 17 Jun 2025 11:53:27 -0700 Subject: [PATCH 2/4] It builds/works --- .../FabricXamlControl.cpp | 166 +++++++++++ .../FabricXamlControl.h | 269 ++++++++++++++++++ .../Microsoft.ReactNative.Xaml.vcxproj | 1 + .../ReactPackageProvider.idl | 7 + vnext/Microsoft.ReactNative.Xaml/XamlHost.cpp | 1 - 5 files changed, 443 insertions(+), 1 deletion(-) create mode 100644 vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.cpp create mode 100644 vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.h diff --git a/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.cpp b/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.cpp new file mode 100644 index 00000000000..a7836c41392 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.cpp @@ -0,0 +1,166 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" + +#if !defined(RNW_NEW_ARCH) +static_assert(false, "This module requires RNW_NEW_ARCH to be defined."); +#endif + +#include "FabricXamlControl.h" + +#include + +#include + +#include +#include + +#include + +namespace winrt::Microsoft::ReactNative::Xaml { + +template +void CustomRegisterXamlControlNativeComponent( + winrt::hstring name, + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function + builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + name, [name, builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = + builder.as(); + + builder.SetCreateProps([name]( + winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps &cloneFrom) noexcept { + return winrt::make(name, 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 != + &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::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 != + &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::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 ( + &TUserData::MountChildComponentView != + &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::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 != + &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::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( + [name](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(name); + if constexpr ( + &TUserData::Initialize != + &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr ( + &TUserData::CreateVisual != + &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + // I suppose we should return null here since we're not backed by a visual? + // No, it looks like in CompositionViewComponentView.cpp ViewComponentView::ensureVisual that this will + // fail. + // TODO: Don't create a dummy visual here. + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace winrt::Microsoft::ReactNative::Xaml + +void RegisterXamlControl(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) { + winrt::Microsoft::ReactNative::Xaml::CustomRegisterXamlControlNativeComponent< + winrt::Microsoft::ReactNative::Xaml::XamlControlComponentView>( + winrt::hstring{L"FX_StackPanel"}, + packageBuilder, + [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { + UNREFERENCED_PARAMETER(builder); + // TODO: Do we need to do anything here? + }); + + winrt::Microsoft::ReactNative::Xaml::CustomRegisterXamlControlNativeComponent< + winrt::Microsoft::ReactNative::Xaml::XamlControlComponentView>( + winrt::hstring{L"FX_Button"}, + packageBuilder, + [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { + UNREFERENCED_PARAMETER(builder); + // TODO: Do we need to do anything here? + }); + + winrt::Microsoft::ReactNative::Xaml::CustomRegisterXamlControlNativeComponent< + winrt::Microsoft::ReactNative::Xaml::XamlControlComponentView>( + winrt::hstring{L"FX_CalendarView"}, + packageBuilder, + [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { + UNREFERENCED_PARAMETER(builder); + // TODO: Do we need to do anything here? + }); +} \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.h b/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.h new file mode 100644 index 00000000000..7151278d040 --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.h @@ -0,0 +1,269 @@ +#pragma once + +#if !defined(RNW_NEW_ARCH) +static_assert(false, "This module requires RNW_NEW_ARCH to be defined."); +#endif + +#include + +#include + +#include +#include + +#include + +#include + +inline std::wstring ToWideString(const char *str) { + int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, nullptr, 0); + if (len == 0) { + return nullptr; // Conversion error + } + + // Allocate a wstring with buffer size of len + std::wstring result(len, L'\0'); + + // Convert the std::string to BSTR + MultiByteToWideChar(CP_UTF8, 0, str, -1, &result[0], len); + + return result; +} + +namespace winrt::Microsoft::ReactNative::Xaml { + +// A FabricXamlControl is a control that represents a generic Xaml element. +// The m_xamlTypeName field tells us what kind of Xaml element. +// A tree of FabricXamlControls must have a XamlHost as a root. +REACT_STRUCT(FabricXamlControlProps) +struct FabricXamlControlProps + : winrt::implements { + FabricXamlControlProps( + winrt::hstring name, + winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps &cloneFrom) + : ViewProps(props), xamlTypeName(name) { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + label = cloneFromProps->label; + xamlTypeName = cloneFromProps->xamlTypeName; + } + } + + 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; + + REACT_FIELD(text) + std::string text; + + REACT_FIELD(content) + // winrt::IInspectable content; + winrt::Microsoft::ReactNative::JSValue content; + + REACT_FIELD(width) + std::optional width; + + REACT_FIELD(height) + std::optional height; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; + + winrt::hstring xamlTypeName; +}; + +struct FabricXamlControlEventEmitter { + FabricXamlControlEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseFabricXamlControl { + 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; +}; + +struct XamlControlComponentView : public winrt::implements, + BaseFabricXamlControl { + XamlControlComponentView(winrt::hstring name) : m_xamlTypeName(name) { + ::OutputDebugString(L"Microsoft::ReactNative::Xaml constructor\n"); + ::OutputDebugString(m_xamlTypeName.c_str()); + ::OutputDebugString(L"\n"); + } + + // IXamlControl + winrt::Microsoft::UI::Xaml::UIElement GetXamlElement() { + return GetXamlElementInternal(); + } + + // MountChildComponentView will only be called if this method is overridden + void MountChildComponentView( + const winrt::Microsoft::ReactNative::ComponentView & /*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept override { + // We're adding a child Xaml element to this Xaml element. + auto child = args.Child(); + auto userData = child.UserData(); + //auto childXamlControl = userData.as(); + auto childXamlControl = userData.as(); + if (childXamlControl) { + auto childXamlElement = childXamlControl.GetXamlElement(); + auto thisElement = GetXamlElement(); + AddXamlChild(thisElement, childXamlElement, args.Index()); + } + } + + void UnmountChildComponentView( + const winrt::Microsoft::ReactNative::ComponentView & /*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept override { + // We're adding a child Xaml element to this Xaml element. + auto child = args.Child(); + auto userData = child.UserData(); + auto childXamlControl = userData.as(); + if (childXamlControl) { + auto thisElement = GetXamlElement(); + RemoveXamlChild(thisElement, args.Index()); + } + } + + void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView & /*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr & /*oldProps*/) noexcept override { + auto xamlControl = GetXamlElement(); + + if (newProps != nullptr) { + if (newProps->content.Type() == winrt::Microsoft::ReactNative::JSValueType::String) { + auto content = newProps->content.AsString(); + // const std::wstring url16 = Microsoft::Common::Unicode::Utf8ToUtf16(content); + auto string16 = ToWideString(content.c_str()); + winrt::hstring contentHString(string16.c_str()); + xamlControl.SetValue( + winrt::Microsoft::UI::Xaml::Controls::ContentControl::ContentProperty(), winrt::box_value(contentHString)); + } else if (newProps->content.Type() == winrt::Microsoft::ReactNative::JSValueType::Null) { + // xamlControl.SetValue(winrt::Microsoft::UI::Xaml::Controls::ContentControl::ContentProperty, + // winrt::hstring{L""}); + } else { + // TODO: Better error handling here. + ::OutputDebugString(L"UpdateProps: I don't recognize this type.\n"); + } + + if (newProps->width) { + xamlControl.as().Width(newProps->width.value()); + } + if (newProps->height) { + xamlControl.as().Height(newProps->height.value()); + } + } + } + + void FinalizeUpdate( + const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept override { + UNREFERENCED_PARAMETER(mask); + view.Mounted([](const winrt::IInspectable &, const winrt::Microsoft::ReactNative::ComponentView &view) { + UNREFERENCED_PARAMETER(view); + // Do mounted things (?) + }); + ::OutputDebugString(L"FinalizeUpdate\n"); + } + + static void AddXamlChild( + winrt::Microsoft::UI::Xaml::UIElement parent, + winrt::Microsoft::UI::Xaml::UIElement child, + uint32_t index) { + // TODO: Support all kinds of Xaml panels and elements that can accept children. + auto panel = parent.as(); + panel.Children().InsertAt(index, child); + } + + static void RemoveXamlChild(winrt::Microsoft::UI::Xaml::UIElement parent, uint32_t index) { + // TODO: Support all kinds of Xaml panels and elements that can accept children. + auto panel = parent.as(); + auto children = panel.Children(); + children.RemoveAt(index); + } + + winrt::Microsoft::UI::Xaml::UIElement GetXamlElementInternal() { + if (!m_xamlElement) { + if (wcscmp(m_xamlTypeName.c_str(), L"FX_StackPanel") == 0) { + m_xamlElement = winrt::Microsoft::UI::Xaml::Controls::StackPanel(); + } else if (wcscmp(m_xamlTypeName.c_str(), L"FX_Button") == 0) { + m_xamlElement = winrt::Microsoft::UI::Xaml::Controls::Button(); + } else if (wcscmp(m_xamlTypeName.c_str(), L"FX_CalendarView") == 0) { + m_xamlElement = winrt::Microsoft::UI::Xaml::Controls::CalendarView(); + } else { + throw std::exception("Unknown XAML control type"); + } + } + return m_xamlElement; + } + + private: + winrt::Microsoft::UI::Xaml::UIElement m_xamlElement{nullptr}; + winrt::hstring m_xamlTypeName; +}; + +} // namespace winrt::Microsoft::ReactNative::Xaml + +// #endif // #if defined(RNW_NEW_ARCH) \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj b/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj index b12f7a1e40b..30a8bed18e1 100644 --- a/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj +++ b/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj @@ -126,6 +126,7 @@ + diff --git a/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.idl b/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.idl index f8f7acbe260..5029dc3f768 100644 --- a/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.idl +++ b/vnext/Microsoft.ReactNative.Xaml/ReactPackageProvider.idl @@ -6,4 +6,11 @@ namespace Microsoft.ReactNative.Xaml { ReactPackageProvider(); }; + + [webhosthidden] + interface IXamlControl + { + Microsoft.UI.Xaml.UIElement GetXamlElement(); + } + } diff --git a/vnext/Microsoft.ReactNative.Xaml/XamlHost.cpp b/vnext/Microsoft.ReactNative.Xaml/XamlHost.cpp index d47d6c6b7e2..38a430d59aa 100644 --- a/vnext/Microsoft.ReactNative.Xaml/XamlHost.cpp +++ b/vnext/Microsoft.ReactNative.Xaml/XamlHost.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT License. #include "pch.h" -#include "FabricXamlControl.h" #include "XamlApplication.h" #include "XamlHost.h" From 068bb1dd673c00d60b23bbc35291723c5f830355 Mon Sep 17 00:00:00 2001 From: Jesse Collins Date: Thu, 19 Jun 2025 12:57:38 -0700 Subject: [PATCH 3/4] A little cleanup --- .../packages.lock.json | 23 ++ .../SampleAppFabric/packages.lock.json | 21 ++ .../XamlCalendarView/packages.lock.json | 115 ++++++++ .../FabricXamlControl.cpp | 166 ----------- .../FabricXamlControl.h | 269 ------------------ .../Microsoft.ReactNative.Xaml.vcxproj | 1 - .../packages.newarch.lock.json | 98 +++++++ yarn.lock | 250 +++++++++++++++- 8 files changed, 505 insertions(+), 438 deletions(-) create mode 100644 packages/xaml-calendar-view/windows/XamlCalendarView/packages.lock.json delete mode 100644 vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.cpp delete mode 100644 vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.h create mode 100644 vnext/Microsoft.ReactNative.Xaml/packages.newarch.lock.json 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 7d84a365b4f..f7902d3bb09 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric.Package/packages.lock.json +++ b/packages/sample-app-fabric/windows/SampleAppFabric.Package/packages.lock.json @@ -83,6 +83,17 @@ "boost": "[1.83.0, )" } }, + "microsoft.reactnative.xaml": { + "type": "Project", + "dependencies": { + "Common": "[1.0.0, )", + "Folly": "[1.0.0, )", + "Microsoft.ReactNative": "[1.0.0, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", + "ReactCommon": "[1.0.0, )", + "boost": "[1.83.0, )" + } + }, "reactcommon": { "type": "Project", "dependencies": { @@ -95,6 +106,18 @@ "dependencies": { "Microsoft.JavaScript.Hermes": "[0.0.0-2505.2001-0e4bc3b9, )", "Microsoft.ReactNative": "[1.0.0, )", + "Microsoft.ReactNative.Xaml": "[1.0.0, )", + "Microsoft.VCRTForwarders.140": "[1.0.2-rc, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", + "XamlCalendarView": "[1.0.0, )", + "boost": "[1.83.0, )" + } + }, + "xamlcalendarview": { + "type": "Project", + "dependencies": { + "Microsoft.ReactNative": "[1.0.0, )", + "Microsoft.ReactNative.Xaml": "[1.0.0, )", "Microsoft.VCRTForwarders.140": "[1.0.2-rc, )", "Microsoft.WindowsAppSDK": "[1.7.250401001, )", "boost": "[1.83.0, )" diff --git a/packages/sample-app-fabric/windows/SampleAppFabric/packages.lock.json b/packages/sample-app-fabric/windows/SampleAppFabric/packages.lock.json index 48426cb9ce0..c1e727c402e 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric/packages.lock.json +++ b/packages/sample-app-fabric/windows/SampleAppFabric/packages.lock.json @@ -93,12 +93,33 @@ "boost": "[1.83.0, )" } }, + "microsoft.reactnative.xaml": { + "type": "Project", + "dependencies": { + "Common": "[1.0.0, )", + "Folly": "[1.0.0, )", + "Microsoft.ReactNative": "[1.0.0, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", + "ReactCommon": "[1.0.0, )", + "boost": "[1.83.0, )" + } + }, "reactcommon": { "type": "Project", "dependencies": { "Folly": "[1.0.0, )", "boost": "[1.83.0, )" } + }, + "xamlcalendarview": { + "type": "Project", + "dependencies": { + "Microsoft.ReactNative": "[1.0.0, )", + "Microsoft.ReactNative.Xaml": "[1.0.0, )", + "Microsoft.VCRTForwarders.140": "[1.0.2-rc, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", + "boost": "[1.83.0, )" + } } }, "native,Version=v0.0/win": { diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/packages.lock.json b/packages/xaml-calendar-view/windows/XamlCalendarView/packages.lock.json new file mode 100644 index 00000000000..52c6e386192 --- /dev/null +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/packages.lock.json @@ -0,0 +1,115 @@ +{ + "version": 1, + "dependencies": { + "native,Version=v0.0": { + "boost": { + "type": "Direct", + "requested": "[1.83.0, )", + "resolved": "1.83.0", + "contentHash": "cy53VNMzysEMvhBixDe8ujPk67Fcj3v6FPHQnH91NYJNLHpc6jxa2xq9ruCaaJjE4M3YrGSHDi4uUSTGBWw6EQ==" + }, + "Microsoft.VCRTForwarders.140": { + "type": "Direct", + "requested": "[1.0.2-rc, )", + "resolved": "1.0.2-rc", + "contentHash": "/r+sjtEeCIGyDhobIZ5hSmYhC/dSyGZxf1SxYJpElUhB0LMCktOMFs9gXrauXypIFECpVynNyVjAmJt6hjJ5oQ==" + }, + "Microsoft.Windows.CppWinRT": { + "type": "Direct", + "requested": "[2.0.230706.1, )", + "resolved": "2.0.230706.1", + "contentHash": "l0D7oCw/5X+xIKHqZTi62TtV+1qeSz7KVluNFdrJ9hXsst4ghvqQ/Yhura7JqRdZWBXAuDS0G0KwALptdoxweQ==" + }, + "Microsoft.WindowsAppSDK": { + "type": "Direct", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", + "dependencies": { + "Microsoft.Web.WebView2": "1.0.2903.40", + "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" + } + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q==" + }, + "Microsoft.JavaScript.Hermes": { + "type": "Transitive", + "resolved": "0.0.0-2505.2001-0e4bc3b9", + "contentHash": "VNSUBgaGzJ/KkK3Br0b9FORkCgKqke54hi48vG42xRACIlxN+uLFMz0hRo+KHogz+Fsn+ltXicGwQsDVpmaCMg==" + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg==" + }, + "Microsoft.SourceLink.GitHub": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "1.1.1", + "Microsoft.SourceLink.Common": "1.1.1" + } + }, + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" + }, + "Microsoft.Windows.SDK.BuildTools": { + "type": "Transitive", + "resolved": "10.0.22621.756", + "contentHash": "7ZL2sFSioYm1Ry067Kw1hg0SCcW5kuVezC2SwjGbcPE61Nn+gTbH86T73G3LcEOVj0S3IZzNuE/29gZvOLS7VA==" + }, + "common": { + "type": "Project", + "dependencies": { + "boost": "[1.83.0, )" + } + }, + "fmt": { + "type": "Project" + }, + "folly": { + "type": "Project", + "dependencies": { + "boost": "[1.83.0, )", + "fmt": "[1.0.0, )" + } + }, + "microsoft.reactnative": { + "type": "Project", + "dependencies": { + "Common": "[1.0.0, )", + "Folly": "[1.0.0, )", + "Microsoft.JavaScript.Hermes": "[0.0.0-2505.2001-0e4bc3b9, )", + "Microsoft.SourceLink.GitHub": "[1.1.1, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", + "ReactCommon": "[1.0.0, )", + "boost": "[1.83.0, )" + } + }, + "microsoft.reactnative.xaml": { + "type": "Project", + "dependencies": { + "Common": "[1.0.0, )", + "Folly": "[1.0.0, )", + "Microsoft.ReactNative": "[1.0.0, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", + "ReactCommon": "[1.0.0, )", + "boost": "[1.83.0, )" + } + }, + "reactcommon": { + "type": "Project", + "dependencies": { + "Folly": "[1.0.0, )", + "boost": "[1.83.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.cpp b/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.cpp deleted file mode 100644 index a7836c41392..00000000000 --- a/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#include "pch.h" - -#if !defined(RNW_NEW_ARCH) -static_assert(false, "This module requires RNW_NEW_ARCH to be defined."); -#endif - -#include "FabricXamlControl.h" - -#include - -#include - -#include -#include - -#include - -namespace winrt::Microsoft::ReactNative::Xaml { - -template -void CustomRegisterXamlControlNativeComponent( - winrt::hstring name, - winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, - std::function - builderCallback) noexcept { - packageBuilder.as().AddViewComponent( - name, [name, builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { - auto compBuilder = - builder.as(); - - builder.SetCreateProps([name]( - winrt::Microsoft::ReactNative::ViewProps props, - const winrt::Microsoft::ReactNative::IComponentProps &cloneFrom) noexcept { - return winrt::make(name, 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 != - &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::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 != - &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::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 ( - &TUserData::MountChildComponentView != - &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::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 != - &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::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( - [name](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { - auto userData = winrt::make_self(name); - if constexpr ( - &TUserData::Initialize != - &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::Initialize) { - userData->Initialize(view); - } - view.UserData(*userData); - }); - - if constexpr ( - &TUserData::CreateVisual != - &winrt::Microsoft::ReactNative::Xaml::BaseFabricXamlControl::CreateVisual) { - compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { - // I suppose we should return null here since we're not backed by a visual? - // No, it looks like in CompositionViewComponentView.cpp ViewComponentView::ensureVisual that this will - // fail. - // TODO: Don't create a dummy visual here. - auto userData = view.UserData().as(); - return userData->CreateVisual(view); - }); - } - - // Allow app to further customize the builder - if (builderCallback) { - builderCallback(compBuilder); - } - }); -} - -} // namespace winrt::Microsoft::ReactNative::Xaml - -void RegisterXamlControl(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) { - winrt::Microsoft::ReactNative::Xaml::CustomRegisterXamlControlNativeComponent< - winrt::Microsoft::ReactNative::Xaml::XamlControlComponentView>( - winrt::hstring{L"FX_StackPanel"}, - packageBuilder, - [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { - UNREFERENCED_PARAMETER(builder); - // TODO: Do we need to do anything here? - }); - - winrt::Microsoft::ReactNative::Xaml::CustomRegisterXamlControlNativeComponent< - winrt::Microsoft::ReactNative::Xaml::XamlControlComponentView>( - winrt::hstring{L"FX_Button"}, - packageBuilder, - [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { - UNREFERENCED_PARAMETER(builder); - // TODO: Do we need to do anything here? - }); - - winrt::Microsoft::ReactNative::Xaml::CustomRegisterXamlControlNativeComponent< - winrt::Microsoft::ReactNative::Xaml::XamlControlComponentView>( - winrt::hstring{L"FX_CalendarView"}, - packageBuilder, - [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { - UNREFERENCED_PARAMETER(builder); - // TODO: Do we need to do anything here? - }); -} \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.h b/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.h deleted file mode 100644 index 7151278d040..00000000000 --- a/vnext/Microsoft.ReactNative.Xaml/FabricXamlControl.h +++ /dev/null @@ -1,269 +0,0 @@ -#pragma once - -#if !defined(RNW_NEW_ARCH) -static_assert(false, "This module requires RNW_NEW_ARCH to be defined."); -#endif - -#include - -#include - -#include -#include - -#include - -#include - -inline std::wstring ToWideString(const char *str) { - int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, nullptr, 0); - if (len == 0) { - return nullptr; // Conversion error - } - - // Allocate a wstring with buffer size of len - std::wstring result(len, L'\0'); - - // Convert the std::string to BSTR - MultiByteToWideChar(CP_UTF8, 0, str, -1, &result[0], len); - - return result; -} - -namespace winrt::Microsoft::ReactNative::Xaml { - -// A FabricXamlControl is a control that represents a generic Xaml element. -// The m_xamlTypeName field tells us what kind of Xaml element. -// A tree of FabricXamlControls must have a XamlHost as a root. -REACT_STRUCT(FabricXamlControlProps) -struct FabricXamlControlProps - : winrt::implements { - FabricXamlControlProps( - winrt::hstring name, - winrt::Microsoft::ReactNative::ViewProps props, - const winrt::Microsoft::ReactNative::IComponentProps &cloneFrom) - : ViewProps(props), xamlTypeName(name) { - if (cloneFrom) { - auto cloneFromProps = cloneFrom.as(); - label = cloneFromProps->label; - xamlTypeName = cloneFromProps->xamlTypeName; - } - } - - 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; - - REACT_FIELD(text) - std::string text; - - REACT_FIELD(content) - // winrt::IInspectable content; - winrt::Microsoft::ReactNative::JSValue content; - - REACT_FIELD(width) - std::optional width; - - REACT_FIELD(height) - std::optional height; - - const winrt::Microsoft::ReactNative::ViewProps ViewProps; - - winrt::hstring xamlTypeName; -}; - -struct FabricXamlControlEventEmitter { - FabricXamlControlEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) - : m_eventEmitter(eventEmitter) {} - - private: - winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; -}; - -template -struct BaseFabricXamlControl { - 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; -}; - -struct XamlControlComponentView : public winrt::implements, - BaseFabricXamlControl { - XamlControlComponentView(winrt::hstring name) : m_xamlTypeName(name) { - ::OutputDebugString(L"Microsoft::ReactNative::Xaml constructor\n"); - ::OutputDebugString(m_xamlTypeName.c_str()); - ::OutputDebugString(L"\n"); - } - - // IXamlControl - winrt::Microsoft::UI::Xaml::UIElement GetXamlElement() { - return GetXamlElementInternal(); - } - - // MountChildComponentView will only be called if this method is overridden - void MountChildComponentView( - const winrt::Microsoft::ReactNative::ComponentView & /*view*/, - const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept override { - // We're adding a child Xaml element to this Xaml element. - auto child = args.Child(); - auto userData = child.UserData(); - //auto childXamlControl = userData.as(); - auto childXamlControl = userData.as(); - if (childXamlControl) { - auto childXamlElement = childXamlControl.GetXamlElement(); - auto thisElement = GetXamlElement(); - AddXamlChild(thisElement, childXamlElement, args.Index()); - } - } - - void UnmountChildComponentView( - const winrt::Microsoft::ReactNative::ComponentView & /*view*/, - const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept override { - // We're adding a child Xaml element to this Xaml element. - auto child = args.Child(); - auto userData = child.UserData(); - auto childXamlControl = userData.as(); - if (childXamlControl) { - auto thisElement = GetXamlElement(); - RemoveXamlChild(thisElement, args.Index()); - } - } - - void UpdateProps( - const winrt::Microsoft::ReactNative::ComponentView & /*view*/, - const winrt::com_ptr &newProps, - const winrt::com_ptr & /*oldProps*/) noexcept override { - auto xamlControl = GetXamlElement(); - - if (newProps != nullptr) { - if (newProps->content.Type() == winrt::Microsoft::ReactNative::JSValueType::String) { - auto content = newProps->content.AsString(); - // const std::wstring url16 = Microsoft::Common::Unicode::Utf8ToUtf16(content); - auto string16 = ToWideString(content.c_str()); - winrt::hstring contentHString(string16.c_str()); - xamlControl.SetValue( - winrt::Microsoft::UI::Xaml::Controls::ContentControl::ContentProperty(), winrt::box_value(contentHString)); - } else if (newProps->content.Type() == winrt::Microsoft::ReactNative::JSValueType::Null) { - // xamlControl.SetValue(winrt::Microsoft::UI::Xaml::Controls::ContentControl::ContentProperty, - // winrt::hstring{L""}); - } else { - // TODO: Better error handling here. - ::OutputDebugString(L"UpdateProps: I don't recognize this type.\n"); - } - - if (newProps->width) { - xamlControl.as().Width(newProps->width.value()); - } - if (newProps->height) { - xamlControl.as().Height(newProps->height.value()); - } - } - } - - void FinalizeUpdate( - const winrt::Microsoft::ReactNative::ComponentView &view, - winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept override { - UNREFERENCED_PARAMETER(mask); - view.Mounted([](const winrt::IInspectable &, const winrt::Microsoft::ReactNative::ComponentView &view) { - UNREFERENCED_PARAMETER(view); - // Do mounted things (?) - }); - ::OutputDebugString(L"FinalizeUpdate\n"); - } - - static void AddXamlChild( - winrt::Microsoft::UI::Xaml::UIElement parent, - winrt::Microsoft::UI::Xaml::UIElement child, - uint32_t index) { - // TODO: Support all kinds of Xaml panels and elements that can accept children. - auto panel = parent.as(); - panel.Children().InsertAt(index, child); - } - - static void RemoveXamlChild(winrt::Microsoft::UI::Xaml::UIElement parent, uint32_t index) { - // TODO: Support all kinds of Xaml panels and elements that can accept children. - auto panel = parent.as(); - auto children = panel.Children(); - children.RemoveAt(index); - } - - winrt::Microsoft::UI::Xaml::UIElement GetXamlElementInternal() { - if (!m_xamlElement) { - if (wcscmp(m_xamlTypeName.c_str(), L"FX_StackPanel") == 0) { - m_xamlElement = winrt::Microsoft::UI::Xaml::Controls::StackPanel(); - } else if (wcscmp(m_xamlTypeName.c_str(), L"FX_Button") == 0) { - m_xamlElement = winrt::Microsoft::UI::Xaml::Controls::Button(); - } else if (wcscmp(m_xamlTypeName.c_str(), L"FX_CalendarView") == 0) { - m_xamlElement = winrt::Microsoft::UI::Xaml::Controls::CalendarView(); - } else { - throw std::exception("Unknown XAML control type"); - } - } - return m_xamlElement; - } - - private: - winrt::Microsoft::UI::Xaml::UIElement m_xamlElement{nullptr}; - winrt::hstring m_xamlTypeName; -}; - -} // namespace winrt::Microsoft::ReactNative::Xaml - -// #endif // #if defined(RNW_NEW_ARCH) \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj b/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj index 30a8bed18e1..b12f7a1e40b 100644 --- a/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj +++ b/vnext/Microsoft.ReactNative.Xaml/Microsoft.ReactNative.Xaml.vcxproj @@ -126,7 +126,6 @@ - diff --git a/vnext/Microsoft.ReactNative.Xaml/packages.newarch.lock.json b/vnext/Microsoft.ReactNative.Xaml/packages.newarch.lock.json new file mode 100644 index 00000000000..5729b8a31dd --- /dev/null +++ b/vnext/Microsoft.ReactNative.Xaml/packages.newarch.lock.json @@ -0,0 +1,98 @@ +{ + "version": 1, + "dependencies": { + "native,Version=v0.0": { + "boost": { + "type": "Direct", + "requested": "[1.83.0, )", + "resolved": "1.83.0", + "contentHash": "cy53VNMzysEMvhBixDe8ujPk67Fcj3v6FPHQnH91NYJNLHpc6jxa2xq9ruCaaJjE4M3YrGSHDi4uUSTGBWw6EQ==" + }, + "Microsoft.Windows.CppWinRT": { + "type": "Direct", + "requested": "[2.0.230706.1, )", + "resolved": "2.0.230706.1", + "contentHash": "l0D7oCw/5X+xIKHqZTi62TtV+1qeSz7KVluNFdrJ9hXsst4ghvqQ/Yhura7JqRdZWBXAuDS0G0KwALptdoxweQ==" + }, + "Microsoft.WindowsAppSDK": { + "type": "Direct", + "requested": "[1.7.250401001, )", + "resolved": "1.7.250401001", + "contentHash": "kPsJ2LZoo3Xs/6FtIWMZRGnQ2ZMx9zDa0ZpqRGz1qwZr0gwwlXZJTmngaA1Ym2AHmIa05NtX2jEE2He8CzfhTg==", + "dependencies": { + "Microsoft.Web.WebView2": "1.0.2903.40", + "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" + } + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q==" + }, + "Microsoft.JavaScript.Hermes": { + "type": "Transitive", + "resolved": "0.0.0-2505.2001-0e4bc3b9", + "contentHash": "VNSUBgaGzJ/KkK3Br0b9FORkCgKqke54hi48vG42xRACIlxN+uLFMz0hRo+KHogz+Fsn+ltXicGwQsDVpmaCMg==" + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg==" + }, + "Microsoft.SourceLink.GitHub": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "1.1.1", + "Microsoft.SourceLink.Common": "1.1.1" + } + }, + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.2903.40", + "contentHash": "THrzYAnJgE3+cNH+9Epr44XjoZoRELdVpXlWGPs6K9C9G6TqyDfVCeVAR/Er8ljLitIUX5gaSkPsy9wRhD1sgQ==" + }, + "Microsoft.Windows.SDK.BuildTools": { + "type": "Transitive", + "resolved": "10.0.22621.756", + "contentHash": "7ZL2sFSioYm1Ry067Kw1hg0SCcW5kuVezC2SwjGbcPE61Nn+gTbH86T73G3LcEOVj0S3IZzNuE/29gZvOLS7VA==" + }, + "common": { + "type": "Project", + "dependencies": { + "boost": "[1.83.0, )" + } + }, + "fmt": { + "type": "Project" + }, + "folly": { + "type": "Project", + "dependencies": { + "boost": "[1.83.0, )", + "fmt": "[1.0.0, )" + } + }, + "microsoft.reactnative": { + "type": "Project", + "dependencies": { + "Common": "[1.0.0, )", + "Folly": "[1.0.0, )", + "Microsoft.JavaScript.Hermes": "[0.0.0-2505.2001-0e4bc3b9, )", + "Microsoft.SourceLink.GitHub": "[1.1.1, )", + "Microsoft.WindowsAppSDK": "[1.7.250401001, )", + "ReactCommon": "[1.0.0, )", + "boost": "[1.83.0, )" + } + }, + "reactcommon": { + "type": "Project", + "dependencies": { + "Folly": "[1.0.0, )", + "boost": "[1.83.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 30b99d76022..fe89dcc4faf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2139,6 +2139,11 @@ resolved "https://registry.yarnpkg.com/@react-native-picker/picker/-/picker-2.11.0.tgz#4587fbce6a382adedad74311e96ee10bb2b2d63a" integrity sha512-QuZU6gbxmOID5zZgd/H90NgBnbJ3VV6qVzp6c7/dDrmWdX8S0X5YFYgDcQFjE3dRen9wB9FWnj2VVdPU64adSg== +"@react-native/assets-registry@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.79.0-nightly-20250123-d1028885e.tgz#27842aea1210494ffe6d1f204db9ae11b4bf5e83" + integrity sha512-NaZg/UFnmXdXsNyoKkGxZ7zJQ852fKdzlakMKBjw4hQ1/e9OntFMrfLbDtpXel3pwSUXqzO0UIlPA0i7XADtcg== + "@react-native/assets-registry@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.79.0-nightly-20250303-cee63397b.tgz#1d5f66cc3618c81219728bfc38da1a6e9d44982a" @@ -2149,6 +2154,14 @@ resolved "https://registry.yarnpkg.com/@react-native/assets/-/assets-1.0.0.tgz#c6f9bf63d274bafc8e970628de24986b30a55c8e" integrity sha512-KrwSpS1tKI70wuKl68DwJZYEvXktDHdZMG0k2AXD/rJVSlB23/X2CB2cutVR0HwNMJIal9HOUOBB2rVfa6UGtQ== +"@react-native/babel-plugin-codegen@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.79.0-nightly-20250123-d1028885e.tgz#a33c521722a641812357f0445539fe00a08a89a3" + integrity sha512-UXUgArUtGEbnptllVkUcwCkRxGSZxTSmd1TFfh+JRKUqIFEaZ/AJaNv1JJCecgnhc+Tx3ZkMVk0HDS/TAYrPkA== + dependencies: + "@babel/traverse" "^7.25.3" + "@react-native/codegen" "0.79.0-nightly-20250123-d1028885e" + "@react-native/babel-plugin-codegen@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.79.0-nightly-20250303-cee63397b.tgz#e00dce8bdd920c6fc159746a45073f5230a82157" @@ -2157,6 +2170,57 @@ "@babel/traverse" "^7.25.3" "@react-native/codegen" "0.79.0-nightly-20250303-cee63397b" +"@react-native/babel-preset@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.79.0-nightly-20250123-d1028885e.tgz#fd1b3b1ef836b1ae3498b341d7ebeb559b3d6dfc" + integrity sha512-x1cvlM9E3n14r30ROAoIICHpLJlNVeAAVcf9SLp2LC91UwcxtSlu5OfMIuOQBhS0lAq1ORH5BP2ALK7B9e08Ow== + dependencies: + "@babel/core" "^7.25.2" + "@babel/plugin-proposal-export-default-from" "^7.24.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-default-from" "^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.24.7" + "@babel/plugin-transform-async-generator-functions" "^7.25.4" + "@babel/plugin-transform-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoping" "^7.25.0" + "@babel/plugin-transform-class-properties" "^7.25.4" + "@babel/plugin-transform-classes" "^7.25.4" + "@babel/plugin-transform-computed-properties" "^7.24.7" + "@babel/plugin-transform-destructuring" "^7.24.8" + "@babel/plugin-transform-flow-strip-types" "^7.25.2" + "@babel/plugin-transform-for-of" "^7.24.7" + "@babel/plugin-transform-function-name" "^7.25.1" + "@babel/plugin-transform-literals" "^7.25.2" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.8" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" + "@babel/plugin-transform-numeric-separator" "^7.24.7" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-optional-catch-binding" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.8" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-react-display-name" "^7.24.7" + "@babel/plugin-transform-react-jsx" "^7.25.2" + "@babel/plugin-transform-react-jsx-self" "^7.24.7" + "@babel/plugin-transform-react-jsx-source" "^7.24.7" + "@babel/plugin-transform-regenerator" "^7.24.7" + "@babel/plugin-transform-runtime" "^7.24.7" + "@babel/plugin-transform-shorthand-properties" "^7.24.7" + "@babel/plugin-transform-spread" "^7.24.7" + "@babel/plugin-transform-sticky-regex" "^7.24.7" + "@babel/plugin-transform-typescript" "^7.25.2" + "@babel/plugin-transform-unicode-regex" "^7.24.7" + "@babel/template" "^7.25.0" + "@react-native/babel-plugin-codegen" "0.79.0-nightly-20250123-d1028885e" + babel-plugin-syntax-hermes-parser "0.25.1" + babel-plugin-transform-flow-enums "^0.0.2" + react-refresh "^0.14.0" + "@react-native/babel-preset@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.79.0-nightly-20250303-cee63397b.tgz#cbe7d5d192f6f0e77488fa7a70b9860dd5a86966" @@ -2208,6 +2272,19 @@ babel-plugin-transform-flow-enums "^0.0.2" react-refresh "^0.14.0" +"@react-native/codegen@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.79.0-nightly-20250123-d1028885e.tgz#48b966e2aec0ed1d12fd40166c780457e82eb9b5" + integrity sha512-ttKR4I3qOZApmiGmOWyF7EkQzP5JCOQAO3y99LCBS/hMNZMMBxe2dV9BO8MdKBPSunYn50P53BgLkOHRYIi7Vg== + dependencies: + "@babel/parser" "^7.25.3" + glob "^7.1.1" + hermes-parser "0.25.1" + invariant "^2.2.4" + jscodeshift "^17.0.0" + nullthrows "^1.1.1" + yargs "^17.6.2" + "@react-native/codegen@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.79.0-nightly-20250303-cee63397b.tgz#14e2ef8ca15c7d917a650583b234748e3ab5f38d" @@ -2221,6 +2298,22 @@ nullthrows "^1.1.1" yargs "^17.6.2" +"@react-native/community-cli-plugin@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.79.0-nightly-20250123-d1028885e.tgz#7cfadc81c68f5ac4006fb3a02b388452ce68df36" + integrity sha512-vJB9IwXrmI/jMIQttw/kvMpPLasp0kS1TUUK+4gVmXz6qgf4CcX4ABtys9fGVpLRc20yalPWB4jpcN8OcrtbyQ== + dependencies: + "@react-native/dev-middleware" "0.79.0-nightly-20250123-d1028885e" + "@react-native/metro-babel-transformer" "0.79.0-nightly-20250123-d1028885e" + chalk "^4.0.0" + debug "^2.2.0" + invariant "^2.2.4" + metro "^0.81.0" + metro-config "^0.81.0" + metro-core "^0.81.0" + readline "^1.3.0" + semver "^7.1.3" + "@react-native/community-cli-plugin@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.79.0-nightly-20250303-cee63397b.tgz#74bb4ad8f4c0dfc85fd1a4aafc0637055ca7a37f" @@ -2235,11 +2328,33 @@ metro-core "^0.81.0" semver "^7.1.3" +"@react-native/debugger-frontend@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.79.0-nightly-20250123-d1028885e.tgz#1e6e1fd661d3ae5db8711f54ab985d26acaddcfe" + integrity sha512-TqzdEZMCGd6fV1pXfFj6RlpRWGmkOq1ZhillAuHxpjCaIc5AtKMYQnS5fwd3B0bicmbf0T2f35Vqxrxp4Jbh6Q== + "@react-native/debugger-frontend@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.79.0-nightly-20250303-cee63397b.tgz#11946f4790cdfff351e1aed3dc956006f0881fb2" integrity sha512-hHFJpRuCoVGzvlJxBdZFl6SKdG1GCwQY+hlxyWs60+DW9hwDmWE+rz9WBU9+6zw5pnmKTEpd/zZWz3MrTWWkUA== +"@react-native/dev-middleware@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.79.0-nightly-20250123-d1028885e.tgz#9c2cd8da7586cfa9baa5574eec6ab7e2643a102a" + integrity sha512-UWBdJaKIgaxiKNRmVCVfkxvNS5hPQY/BUyrUmJ0LrmEwJoFRkMk6rkHT/sYPRCVANHJAmrHbc+L2go5k40TKKQ== + dependencies: + "@isaacs/ttlcache" "^1.4.1" + "@react-native/debugger-frontend" "0.79.0-nightly-20250123-d1028885e" + chrome-launcher "^0.15.2" + chromium-edge-launcher "^0.2.0" + connect "^3.6.5" + debug "^2.2.0" + nullthrows "^1.1.1" + open "^7.0.3" + selfsigned "^2.4.1" + serve-static "^1.16.2" + ws "^6.2.3" + "@react-native/dev-middleware@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.79.0-nightly-20250303-cee63397b.tgz#7fd19b43d316184c3d28955cf55cdc99242c220f" @@ -2280,16 +2395,36 @@ resolved "https://registry.yarnpkg.com/@react-native/eslint-plugin/-/eslint-plugin-0.79.0-nightly-20250123-d1028885e.tgz#7983608a83b724ab2f31d2e84e67fb5f9a7ad3b1" integrity sha512-vYrjxRh3wvL9MmmmsO52keyONK8O7CqayB1gvgSf/EeptcnnCpd0YdJ06NU54aB3zh6p+k4vkxHliNFqpBTFBg== +"@react-native/gradle-plugin@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.79.0-nightly-20250123-d1028885e.tgz#290df4b33dd0ea25c1c36c824a018d0f8c9b3367" + integrity sha512-ZKQYCjYAHWhaawiirLvQpOyAiYVwTa6eZlvXZ1Mee32kGPP4TYMw4mgrFmP6SKySEI1/4pPCLK77I7eukOIVow== + "@react-native/gradle-plugin@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.79.0-nightly-20250303-cee63397b.tgz#90b61e57a79007bcce5bf58d64f1b7a724489379" integrity sha512-Fw5RsMDDODT4YUtxt53ytTpgfBPhDD/lehRhYVyO4Ud6bN6oUiS8lBdZWKo/7B3mwDh9OEt0ppeBOYTZwirRZA== +"@react-native/js-polyfills@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.79.0-nightly-20250123-d1028885e.tgz#93f36db2f1fc8a0e2fd692108623bc9a141cd1c9" + integrity sha512-kfsivK3v0SogoURYxUs80Cam+7kPpeQSkOdfWUj8gVdde8dA3XAwb78zn1NLUMCl+6nGwWzZ94/y7OZF7Z0EwA== + "@react-native/js-polyfills@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.79.0-nightly-20250303-cee63397b.tgz#20f5b19d244185686262153d0bc93f327f84c9d7" integrity sha512-uPQt+6fE39CpOksFfQIj+suThswQxxLJUf2aaJHZvvTClbXqVrFhjGoCADZ+XSIqrbIK1MIsYA6kCtMCuGmSgA== +"@react-native/metro-babel-transformer@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.79.0-nightly-20250123-d1028885e.tgz#45d06b98331c86086e9b659dcfc9c2b53e481e27" + integrity sha512-l89671iQtDc+UsbQYpbhC4jguBfVk1+Y9lb1qPTIzb2oRKZB+p4HCsazvrrNZ0GX/iuadUL4YLZnboVEng8kFQ== + dependencies: + "@babel/core" "^7.25.2" + "@react-native/babel-preset" "0.79.0-nightly-20250123-d1028885e" + hermes-parser "0.25.1" + nullthrows "^1.1.1" + "@react-native/metro-babel-transformer@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.79.0-nightly-20250303-cee63397b.tgz#4f345cf45fbf86e71de30ee7fa3e59cc30d7cc6d" @@ -2300,6 +2435,16 @@ hermes-parser "0.25.1" nullthrows "^1.1.1" +"@react-native/metro-config@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/metro-config/-/metro-config-0.79.0-nightly-20250123-d1028885e.tgz#0767c94a9f6b7cc23bf924e9e40863373b025c70" + integrity sha512-8YeySMhvRXWroqB1n49WMBXbqX/m4x910VOa7xmAczyzG90VcUI+vORkUk4ZmY3nufVKkDs0a0Y9wOmu0d3xEQ== + dependencies: + "@react-native/js-polyfills" "0.79.0-nightly-20250123-d1028885e" + "@react-native/metro-babel-transformer" "0.79.0-nightly-20250123-d1028885e" + metro-config "^0.81.0" + metro-runtime "^0.81.0" + "@react-native/metro-config@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/metro-config/-/metro-config-0.79.0-nightly-20250303-cee63397b.tgz#5f709afb51fa2732dac79288a28c0ce35fab3729" @@ -2310,6 +2455,11 @@ metro-config "^0.81.0" metro-runtime "^0.81.0" +"@react-native/normalize-colors@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.79.0-nightly-20250123-d1028885e.tgz#c2f5f3790cea75c4452d7171c503a57cbb329947" + integrity sha512-DUN8UAD+YDL8Jdqi5BIvnnzv5tKNkbc7+Om+l0fKvYkGiOWdw9jAyQPFejNPLBc9sUSG5aBbRcN0qL6kIIkpZw== + "@react-native/normalize-colors@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.79.0-nightly-20250303-cee63397b.tgz#39ab0aae6aa677d9bedbfd63696a20d2e591f622" @@ -2322,6 +2472,14 @@ dependencies: nullthrows "^1.1.1" +"@react-native/virtualized-lists@0.79.0-nightly-20250123-d1028885e": + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.79.0-nightly-20250123-d1028885e.tgz#50e6840c0f9f93547ce94b470efa75bca21cd3a1" + integrity sha512-nhEiOU3tlK5xtaQNgp/Twus2xGgFw6XSsf/29YvUoi2xq6gdG+Xt5vfdu/qq2wrNa50bjSkV9+BjH12kPWDUkg== + dependencies: + invariant "^2.2.4" + nullthrows "^1.1.1" + "@react-native/virtualized-lists@0.79.0-nightly-20250303-cee63397b": version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.79.0-nightly-20250303-cee63397b.tgz#9831d218b32908af6f7284bdd299dcfeb12d61ac" @@ -2330,6 +2488,32 @@ invariant "^2.2.4" nullthrows "^1.1.1" +"@rnw-scripts/eslint-config@1.2.34": + version "1.2.34" + resolved "https://registry.yarnpkg.com/@rnw-scripts/eslint-config/-/eslint-config-1.2.34.tgz#c76ddf984e55fd1a2609bfbe6dece5ea017d8336" + integrity sha512-G4WoBojT6EX/mca0cWLXSWVU/gXSVm/3/NlLlMCSFJ/O6EklVv/wFtzepHL45XWYiHiG/ng+wSy9VVgjONfsmw== + dependencies: + "@babel/core" "^7.25.2" + "@babel/eslint-parser" "^7.25.1" + "@microsoft/eslint-plugin-sdl" "^0.2.0" + "@react-native/eslint-config" "0.79.0-nightly-20250123-d1028885e" + eslint-config-prettier "^8.5.0" + eslint-plugin-ft-flow "^2.0.1" + hermes-eslint "0.23.1" + +"@rnw-scripts/just-task@2.3.51": + version "2.3.51" + resolved "https://registry.yarnpkg.com/@rnw-scripts/just-task/-/just-task-2.3.51.tgz#675a169f08042559c5b1758e159153ff3d9b0904" + integrity sha512-xV+tJZkL+1L7HdcTAD20VNPjpuDArdEc/xIchp9em0UxV7MyDfwgOwxVb7Uh+ZKhyz/86+nTQo0NtuiQvHAt5w== + dependencies: + "@octokit/rest" "^18.5.3" + "@rnw-scripts/jest-e2e-config" "1.4.11" + "@rnw-scripts/jest-unittest-config" "1.5.11" + depcheck "^1.4.1" + find-up "^4.1.0" + glob "^7.1.6" + just-scripts "^1.3.3" + "@rnx-kit/align-deps@^2.5.0": version "2.5.5" resolved "https://registry.yarnpkg.com/@rnx-kit/align-deps/-/align-deps-2.5.5.tgz#708b4fd65941699e1ef33c728d34bc568e648b73" @@ -2771,6 +2955,13 @@ "@types/node" "*" form-data "^4.0.0" +"@types/node-forge@^1.3.0": + version "1.3.11" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" + integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== + dependencies: + "@types/node" "*" + "@types/node@*": version "22.9.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.0.tgz#b7f16e5c3384788542c72dc3d561a7ceae2c0365" @@ -7591,7 +7782,7 @@ jest-each@^29.7.0: jest-util "^29.7.0" pretty-format "^29.7.0" -jest-environment-node@^29.7.0: +jest-environment-node@^29.6.3, jest-environment-node@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== @@ -9133,6 +9324,11 @@ node-fetch@^2.2.0, node-fetch@^2.6.1, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -9995,7 +10191,7 @@ react-clone-referenced-element@^1.0.1: resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.1.1.tgz#8d76727dc0459788e461741e804a512d20757381" integrity sha512-LZBPvQV8W0B5dFzXFu+D3Tpil8YHS8tO00iFsfXcTLdtpuH7XyvaHqHcoz4hd4uNPQCZ30fceh+s7mLznzMXvg== -react-devtools-core@^6.1.1: +react-devtools-core@^6.0.1, react-devtools-core@^6.1.1: version "6.1.2" resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-6.1.2.tgz#bf4030c4012be8a9201dc1f8a36238c9a5078c98" integrity sha512-ldFwzufLletzCikNJVYaxlxMLu7swJ3T2VrGfzXlMsVhZhPDKXA38DEROidaYZVgMAmQnIjymrmqto5pyfrwPA== @@ -10030,6 +10226,48 @@ react-native-xaml@^0.0.78: dependencies: "@types/react" "*" +react-native@0.79.0-nightly-20250123-d1028885e: + version "0.79.0-nightly-20250123-d1028885e" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.79.0-nightly-20250123-d1028885e.tgz#22848dd2b2afb9fd90cae8916fd07fb47b4e06ff" + integrity sha512-4uVCYZvHWimD0kX8tskSoMOsahfn9o4WhMMjKWyw0V02OxJ8pWhhgZucy+itHc0YWC/tNb9g2aX3EXTpnuqAVA== + dependencies: + "@jest/create-cache-key-function" "^29.6.3" + "@react-native/assets-registry" "0.79.0-nightly-20250123-d1028885e" + "@react-native/codegen" "0.79.0-nightly-20250123-d1028885e" + "@react-native/community-cli-plugin" "0.79.0-nightly-20250123-d1028885e" + "@react-native/gradle-plugin" "0.79.0-nightly-20250123-d1028885e" + "@react-native/js-polyfills" "0.79.0-nightly-20250123-d1028885e" + "@react-native/normalize-colors" "0.79.0-nightly-20250123-d1028885e" + "@react-native/virtualized-lists" "0.79.0-nightly-20250123-d1028885e" + abort-controller "^3.0.0" + anser "^1.4.9" + ansi-regex "^5.0.0" + babel-jest "^29.7.0" + babel-plugin-syntax-hermes-parser "0.25.1" + base64-js "^1.5.1" + chalk "^4.0.0" + commander "^12.0.0" + event-target-shim "^5.0.1" + flow-enums-runtime "^0.0.6" + glob "^7.1.1" + invariant "^2.2.4" + jest-environment-node "^29.6.3" + memoize-one "^5.0.0" + metro-runtime "^0.81.0" + metro-source-map "^0.81.0" + nullthrows "^1.1.1" + pretty-format "^29.7.0" + promise "^8.3.0" + react-devtools-core "^6.0.1" + react-refresh "^0.14.0" + regenerator-runtime "^0.13.2" + scheduler "0.25.0" + semver "^7.1.3" + stacktrace-parser "^0.1.10" + whatwg-fetch "^3.0.0" + ws "^6.2.3" + yargs "^17.6.2" + react-native@0.79.0-nightly-20250303-cee63397b: version "0.79.0-nightly-20250303-cee63397b" resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.79.0-nightly-20250303-cee63397b.tgz#7ca4ee8e894ca3fa3f6d733cdf1bf35346b0c66f" @@ -10566,6 +10804,14 @@ screenshot-desktop@^1.12.2: dependencies: temp "^0.9.4" +selfsigned@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" + integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== + dependencies: + "@types/node-forge" "^1.3.0" + node-forge "^1" + semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" From 205e51d1bc2a35fb1b540d356f7b6db5cbb23815 Mon Sep 17 00:00:00 2001 From: Jesse Collins Date: Fri, 20 Jun 2025 13:17:03 -0700 Subject: [PATCH 4/4] Add a prop and event --- packages/sample-app-fabric/App.tsx | 17 +++++-- packages/sample-app-fabric/b.cmd | 10 +++- .../xaml-calendar-view/src/CalendarView.tsx | 4 +- .../src/CalendarViewNativeComponent.ts | 9 +++- .../XamlCalendarView/XamlCalendarView.cpp | 48 ++++++++++++++++++- .../components/CalendarView/CalendarView.g.h | 23 +++++++-- 6 files changed, 98 insertions(+), 13 deletions(-) diff --git a/packages/sample-app-fabric/App.tsx b/packages/sample-app-fabric/App.tsx index b4cba6dbd1a..26c05e47c37 100644 --- a/packages/sample-app-fabric/App.tsx +++ b/packages/sample-app-fabric/App.tsx @@ -5,7 +5,7 @@ * @format */ -import React from 'react'; +import React, {useState} from 'react'; import type {PropsWithChildren} from 'react'; import { SafeAreaView, @@ -64,6 +64,8 @@ function App(): React.JSX.Element { backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, }; + const [selectedDate, setSelectedDate] = useState(true); + return (
Edit App.tsx to change this. - I'll try showing a CalendarView here: + I'll try showing a CalendarView here (displayMode=1 for month view).
- + { + setSelectedDate(e.nativeEvent.startDate); + }} + /> + +
Selected date: {selectedDate}
+
diff --git a/packages/sample-app-fabric/b.cmd b/packages/sample-app-fabric/b.cmd index 3a60f9a1a14..1c73edfcdc7 100644 --- a/packages/sample-app-fabric/b.cmd +++ b/packages/sample-app-fabric/b.cmd @@ -1,8 +1,14 @@ setlocal pushd ..\.. -call yarn +call yarn || goto :fail popd -call yarn react-native run-windows --msbuildprops RestoreForceEvaluate=true +call yarn react-native run-windows --msbuildprops RestoreForceEvaluate=true || goto :fail + +echo Success! +exit /b 0 + +echo FAILED. +exit /b 1 diff --git a/packages/xaml-calendar-view/src/CalendarView.tsx b/packages/xaml-calendar-view/src/CalendarView.tsx index 047aa321312..8fe23b958df 100644 --- a/packages/xaml-calendar-view/src/CalendarView.tsx +++ b/packages/xaml-calendar-view/src/CalendarView.tsx @@ -6,8 +6,8 @@ import XamlHost from 'react-native-windows/Libraries/Components/Xaml/XamlHost'; function CalendarView(props: any) { return ( - - + + ); } diff --git a/packages/xaml-calendar-view/src/CalendarViewNativeComponent.ts b/packages/xaml-calendar-view/src/CalendarViewNativeComponent.ts index d7e5608b65d..7aab1a336fc 100644 --- a/packages/xaml-calendar-view/src/CalendarViewNativeComponent.ts +++ b/packages/xaml-calendar-view/src/CalendarViewNativeComponent.ts @@ -5,9 +5,16 @@ import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps } from 'react-native'; +import type {DirectEventHandler, Int32} from 'react-native/Libraries/Types/CodegenTypes'; + +type SelectedDatesChangedEvent = Readonly<{ + value: boolean; + startDate: string; +}>; export interface CalendarViewProps extends ViewProps { - label : string; + displayMode : Int32; + onSelectedDatesChanged?: DirectEventHandler; } export default codegenNativeComponent('CalendarView'); diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.cpp b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.cpp index 2d84d2719f4..c1b5b954303 100644 --- a/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.cpp +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/XamlCalendarView.cpp @@ -9,15 +9,59 @@ namespace winrt::XamlCalendarView { struct CalendarView : public winrt::implements, - Codegen::BaseCalendarView { + public Codegen::BaseCalendarView { winrt::Microsoft::UI::Xaml::UIElement GetXamlElement() { if (m_calendarView == nullptr) { - m_calendarView = winrt::Microsoft::UI::Xaml::Controls::CalendarView(); + CreateXamlCalendarView(); } return m_calendarView; } + void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::com_ptr &newProps, + const winrt::com_ptr &oldProps) noexcept override { + Codegen::BaseCalendarView::UpdateProps(view, newProps, oldProps); + + if (m_calendarView && newProps) { + m_calendarView.DisplayMode(static_cast( + newProps->displayMode)); + } + } + + void CreateXamlCalendarView() { + m_calendarView = winrt::Microsoft::UI::Xaml::Controls::CalendarView(); + if (Props()) { + m_calendarView.DisplayMode( + static_cast( + Props()->displayMode)); + } + 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::Controls::CalendarView m_calendarView{ nullptr }; }; diff --git a/packages/xaml-calendar-view/windows/XamlCalendarView/codegen/react/components/CalendarView/CalendarView.g.h b/packages/xaml-calendar-view/windows/XamlCalendarView/codegen/react/components/CalendarView/CalendarView.g.h index a8c748f7ca6..e09befdfeb9 100644 --- a/packages/xaml-calendar-view/windows/XamlCalendarView/codegen/react/components/CalendarView/CalendarView.g.h +++ b/packages/xaml-calendar-view/windows/XamlCalendarView/codegen/react/components/CalendarView/CalendarView.g.h @@ -25,7 +25,7 @@ struct CalendarViewProps : winrt::implements(); - label = cloneFromProps->label; + displayMode = cloneFromProps->displayMode; } } @@ -33,16 +33,33 @@ struct CalendarViewProps : winrt::implements