react-native-windows 0.76.2 → 0.77.0-preview.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (459) hide show
  1. package/.flowconfig +5 -1
  2. package/Libraries/ActionSheetIOS/ActionSheetIOS.d.ts +1 -0
  3. package/Libraries/ActionSheetIOS/ActionSheetIOS.js +13 -0
  4. package/Libraries/Animated/AnimatedEvent.js +1 -1
  5. package/Libraries/Animated/AnimatedImplementation.js +2 -2
  6. package/Libraries/Animated/NativeAnimatedAllowlist.js +20 -9
  7. package/Libraries/Animated/NativeAnimatedAllowlist.windows.js +122 -0
  8. package/Libraries/Animated/animations/Animation.js +60 -25
  9. package/Libraries/Animated/animations/DecayAnimation.js +26 -38
  10. package/Libraries/Animated/animations/SpringAnimation.js +33 -39
  11. package/Libraries/Animated/animations/TimingAnimation.js +34 -42
  12. package/Libraries/Animated/components/AnimatedFlatList.js +1 -1
  13. package/Libraries/Animated/components/AnimatedSectionList.js +3 -1
  14. package/Libraries/Animated/createAnimatedComponent.js +60 -33
  15. package/Libraries/Animated/nodes/AnimatedColor.js +1 -1
  16. package/Libraries/Animated/nodes/AnimatedInterpolation.js +1 -1
  17. package/Libraries/Animated/nodes/AnimatedNode.js +39 -45
  18. package/Libraries/Animated/nodes/AnimatedObject.js +13 -3
  19. package/Libraries/Animated/nodes/AnimatedProps.js +96 -46
  20. package/Libraries/Animated/nodes/AnimatedProps.windows.js +281 -0
  21. package/Libraries/Animated/nodes/AnimatedStyle.js +108 -39
  22. package/Libraries/Animated/nodes/AnimatedStyle.windows.js +251 -0
  23. package/Libraries/Animated/nodes/AnimatedTransform.js +56 -23
  24. package/Libraries/Animated/nodes/AnimatedValue.js +1 -1
  25. package/Libraries/Animated/nodes/AnimatedWithChildren.js +1 -3
  26. package/Libraries/Animated/useAnimatedProps.js +41 -35
  27. package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.d.ts +19 -3
  28. package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +77 -5
  29. package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.windows.js +82 -5
  30. package/Libraries/Components/ActivityIndicator/ActivityIndicator.js +4 -4
  31. package/Libraries/Components/Button.js +9 -4
  32. package/Libraries/Components/Button.windows.js +19 -5
  33. package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js +3 -1
  34. package/Libraries/Components/Glyph/Glyph.js +2 -1
  35. package/Libraries/Components/Keyboard/KeyboardAvoidingView.js +7 -0
  36. package/Libraries/Components/Popup/PopupNativeComponent.js +0 -1
  37. package/Libraries/Components/Pressable/Pressable.js +4 -4
  38. package/Libraries/Components/Pressable/Pressable.windows.js +10 -4
  39. package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +13 -7
  40. package/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js +3 -2
  41. package/Libraries/Components/SafeAreaView/SafeAreaView.js +4 -4
  42. package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +0 -1
  43. package/Libraries/Components/ScrollView/ScrollView.js +49 -88
  44. package/Libraries/Components/ScrollView/ScrollViewCommands.js +1 -1
  45. package/Libraries/Components/ScrollView/ScrollViewContext.js +2 -0
  46. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +0 -2
  47. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.windows.js +0 -5
  48. package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +8 -9
  49. package/Libraries/Components/Switch/Switch.js +8 -6
  50. package/Libraries/Components/Switch/Switch.windows.js +8 -6
  51. package/Libraries/Components/TextInput/InputAccessoryView.js +1 -1
  52. package/Libraries/Components/TextInput/RCTMultilineTextInputNativeComponent.js +4 -4
  53. package/Libraries/Components/TextInput/RCTSingelineTextInputNativeComponent.js +6 -4
  54. package/Libraries/Components/TextInput/RCTTextInputViewConfig.js +2 -1
  55. package/Libraries/Components/TextInput/TextInput.d.ts +27 -4
  56. package/Libraries/Components/TextInput/TextInput.flow.js +36 -19
  57. package/Libraries/Components/TextInput/TextInput.js +37 -13
  58. package/Libraries/Components/TextInput/TextInput.windows.js +47 -16
  59. package/Libraries/Components/TextInput/TextInputState.js +11 -13
  60. package/Libraries/Components/TextInput/TextInputState.windows.js +11 -13
  61. package/Libraries/Components/Touchable/BoundingDimensions.js +11 -3
  62. package/Libraries/Components/Touchable/Position.js +7 -2
  63. package/Libraries/Components/Touchable/Touchable.js +4 -0
  64. package/Libraries/Components/Touchable/Touchable.windows.js +4 -0
  65. package/Libraries/Components/Touchable/TouchableBounce.js +6 -2
  66. package/Libraries/Components/Touchable/TouchableBounce.windows.js +227 -0
  67. package/Libraries/Components/Touchable/TouchableHighlight.js +5 -5
  68. package/Libraries/Components/Touchable/TouchableHighlight.windows.js +5 -5
  69. package/Libraries/Components/Touchable/TouchableNativeFeedback.windows.js +371 -0
  70. package/Libraries/Components/Touchable/TouchableOpacity.js +6 -5
  71. package/Libraries/Components/Touchable/TouchableOpacity.windows.js +11 -5
  72. package/Libraries/Components/Touchable/TouchableWithoutFeedback.js +1 -2
  73. package/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js +9 -3
  74. package/Libraries/Components/View/ReactNativeStyleAttributes.js +6 -1
  75. package/Libraries/Components/View/View.js +4 -4
  76. package/Libraries/Components/View/View.windows.js +88 -57
  77. package/Libraries/Components/View/ViewAccessibility.d.ts +10 -0
  78. package/Libraries/Components/View/ViewAccessibility.windows.js +2 -0
  79. package/Libraries/Components/View/ViewNativeComponent.js +6 -98
  80. package/Libraries/Components/View/ViewPropTypes.d.ts +7 -0
  81. package/Libraries/Components/View/ViewPropTypes.js +0 -3
  82. package/Libraries/Components/View/ViewPropTypes.windows.js +2 -3
  83. package/Libraries/Core/ExceptionsManager.js +50 -29
  84. package/Libraries/Core/ReactNativeVersion.js +3 -3
  85. package/Libraries/Core/__mocks__/NativeExceptionsManager.js +0 -1
  86. package/Libraries/Core/setUpBatchedBridge.js +1 -10
  87. package/Libraries/Core/setUpDeveloperTools.js +1 -5
  88. package/Libraries/Core/setUpErrorHandling.js +20 -18
  89. package/Libraries/Core/setUpReactDevTools.js +107 -8
  90. package/Libraries/Core/setUpSegmentFetcher.js +1 -0
  91. package/Libraries/Core/setUpTimers.js +21 -18
  92. package/Libraries/Debugging/DebuggingOverlay.js +4 -5
  93. package/Libraries/Image/AssetSourceResolver.js +12 -1
  94. package/Libraries/Image/AssetSourceResolver.windows.js +12 -1
  95. package/Libraries/Image/Image.android.js +1 -5
  96. package/Libraries/Image/Image.d.ts +20 -29
  97. package/Libraries/Image/Image.ios.js +0 -2
  98. package/Libraries/Image/Image.windows.js +5 -1
  99. package/Libraries/Image/ImageBackground.js +2 -5
  100. package/Libraries/Image/ImageProps.js +7 -6
  101. package/Libraries/Image/ImageResizeMode.d.ts +8 -1
  102. package/Libraries/Image/ImageResizeMode.js +4 -1
  103. package/Libraries/Image/ImageSource.d.ts +0 -2
  104. package/Libraries/Image/ImageSource.js +0 -2
  105. package/Libraries/Image/ImageTypes.flow.js +11 -9
  106. package/Libraries/Image/ImageUtils.js +6 -3
  107. package/Libraries/Image/ImageViewNativeComponent.js +5 -3
  108. package/Libraries/Inspector/Inspector.js +1 -0
  109. package/Libraries/Inspector/NetworkOverlay.js +4 -0
  110. package/Libraries/Inspector/ReactDevToolsOverlay.js +8 -14
  111. package/Libraries/Inspector/getInspectorDataForViewAtPoint.js +3 -5
  112. package/Libraries/Interaction/InteractionManager.js +6 -1
  113. package/Libraries/Interaction/InteractionManagerStub.js +176 -0
  114. package/Libraries/Interaction/TouchHistoryMath.js +22 -19
  115. package/Libraries/JSInspector/NetworkAgent.js +1 -1
  116. package/Libraries/Lists/FlatList.d.ts +1 -2
  117. package/Libraries/Lists/FlatList.js +2 -2
  118. package/Libraries/Lists/SectionListModern.js +7 -7
  119. package/Libraries/Lists/__flowtests__/FlatList-flowtest.js +2 -2
  120. package/Libraries/Lists/__flowtests__/SectionList-flowtest.js +1 -1
  121. package/Libraries/LogBox/Data/LogBoxData.js +3 -3
  122. package/Libraries/LogBox/LogBox.js +18 -5
  123. package/Libraries/LogBox/LogBoxInspectorContainer.js +1 -1
  124. package/Libraries/LogBox/LogBoxNotificationContainer.js +2 -2
  125. package/Libraries/LogBox/UI/AnsiHighlight.js +26 -17
  126. package/Libraries/LogBox/UI/LogBoxInspectorCodeFrame.js +6 -1
  127. package/Libraries/LogBox/UI/LogBoxInspectorCodeFrame.windows.js +6 -1
  128. package/Libraries/LogBox/UI/LogBoxInspectorHeader.js +1 -1
  129. package/Libraries/LogBox/UI/LogBoxInspectorHeader.windows.js +1 -1
  130. package/Libraries/LogBox/UI/LogBoxInspectorStackFrames.js +1 -1
  131. package/Libraries/LogBox/UI/LogBoxMessage.js +2 -2
  132. package/Libraries/Modal/Modal.d.ts +12 -0
  133. package/Libraries/Modal/Modal.js +31 -4
  134. package/Libraries/Modal/Modal.windows.js +370 -0
  135. package/Libraries/NativeComponent/BaseViewConfig.android.js +72 -1
  136. package/Libraries/NativeComponent/BaseViewConfig.ios.js +2 -1
  137. package/Libraries/NativeComponent/BaseViewConfig.windows.js +3 -11
  138. package/Libraries/NativeComponent/NativeComponentRegistry.js +3 -3
  139. package/Libraries/NativeComponent/StaticViewConfigValidator.js +0 -1
  140. package/Libraries/Network/XHRInterceptor.js +63 -14
  141. package/Libraries/Network/XMLHttpRequest.js +26 -1
  142. package/Libraries/NewAppScreen/components/HermesBadge.js +1 -1
  143. package/Libraries/PermissionsAndroid/PermissionsAndroid.d.ts +49 -2
  144. package/Libraries/PermissionsAndroid/PermissionsAndroid.js +4 -4
  145. package/Libraries/Pressability/HoverState.js +2 -0
  146. package/Libraries/Pressability/Pressability.js +2 -3
  147. package/Libraries/Pressability/Pressability.windows.js +2 -3
  148. package/Libraries/Pressability/usePressability.js +4 -1
  149. package/Libraries/ReactNative/AppContainer.js +1 -1
  150. package/Libraries/ReactNative/AppRegistry.js +1 -11
  151. package/Libraries/ReactNative/DisplayMode.js +1 -1
  152. package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricHostComponent.js +2 -3
  153. package/Libraries/ReactNative/RendererImplementation.js +18 -17
  154. package/Libraries/ReactNative/getCachedComponentWithDebugName.js +1 -3
  155. package/Libraries/ReactNative/renderApplication.js +9 -8
  156. package/Libraries/ReactNative/requireNativeComponent.js +5 -2
  157. package/Libraries/Renderer/shims/ReactFabric.js +3 -3
  158. package/Libraries/Renderer/shims/ReactFeatureFlags.js +2 -2
  159. package/Libraries/Renderer/shims/ReactNative.js +3 -3
  160. package/Libraries/Renderer/shims/ReactNativeTypes.js +22 -35
  161. package/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +5 -6
  162. package/Libraries/Renderer/shims/createReactNativeComponentClass.js +2 -2
  163. package/Libraries/StyleSheet/StyleSheet.js +7 -1
  164. package/Libraries/StyleSheet/StyleSheetTypes.d.ts +13 -2
  165. package/Libraries/StyleSheet/StyleSheetTypes.js +24 -6
  166. package/Libraries/StyleSheet/processBackgroundImage.js +87 -110
  167. package/Libraries/StyleSheet/processTransform.js +3 -34
  168. package/Libraries/Text/Text.js +248 -249
  169. package/Libraries/Text/Text.windows.js +298 -292
  170. package/Libraries/Text/TextNativeComponent.js +0 -1
  171. package/Libraries/Text/TextProps.windows.js +2 -0
  172. package/Libraries/TurboModule/TurboModuleRegistry.js +5 -5
  173. package/Libraries/Types/CoreEventTypes.d.ts +3 -10
  174. package/Libraries/Types/CoreEventTypes.js +4 -6
  175. package/Libraries/Types/CoreEventTypes.windows.js +4 -6
  176. package/Libraries/Utilities/Appearance.js +3 -1
  177. package/Libraries/Utilities/BackHandler.android.js +6 -18
  178. package/Libraries/Utilities/BackHandler.d.ts +0 -4
  179. package/Libraries/Utilities/BackHandler.ios.js +0 -7
  180. package/Libraries/Utilities/BackHandler.windows.js +6 -18
  181. package/Libraries/Utilities/HMRClient.js +3 -4
  182. package/Libraries/Utilities/Platform.flow.js +2 -2
  183. package/Libraries/Utilities/Platform.flow.windows.js +3 -2
  184. package/Libraries/Utilities/__mocks__/BackHandler.js +3 -8
  185. package/Libraries/Utilities/codegenNativeComponent.js +1 -1
  186. package/Libraries/Utilities/useMergeRefs.js +26 -7
  187. package/Libraries/WebSocket/WebSocketEvent.js +4 -1
  188. package/Libraries/WebSocket/WebSocketInterceptor.js +31 -13
  189. package/Libraries/__flowtests__/ReactNativeTypes-flowtest.js +6 -5
  190. package/Libraries/promiseRejectionTrackingOptions.js +1 -1
  191. package/Microsoft.ReactNative/AsynchronousEventBeat.cpp +9 -8
  192. package/Microsoft.ReactNative/AsynchronousEventBeat.h +5 -5
  193. package/Microsoft.ReactNative/CompositionComponentView.idl +2 -1
  194. package/Microsoft.ReactNative/FBReactNativeSpec/FBReactNativeSpecJSI.h +5 -0
  195. package/Microsoft.ReactNative/Fabric/AbiComponentDescriptor.cpp +6 -3
  196. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.cpp +1 -1
  197. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +7 -0
  198. package/Microsoft.ReactNative/Fabric/AbiViewProps.h +2 -0
  199. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +45 -50
  200. package/Microsoft.ReactNative/Fabric/ComponentView.h +14 -22
  201. package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.cpp +943 -0
  202. package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.h +80 -0
  203. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +223 -21
  204. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +19 -1
  205. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +187 -6
  206. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +10 -1
  207. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +8 -32
  208. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +349 -929
  209. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +32 -29
  210. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +9 -2
  211. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +2 -1
  212. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +1 -1
  213. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +181 -123
  214. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +16 -8
  215. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +99 -37
  216. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +25 -3
  217. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +64 -3
  218. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +12 -0
  219. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +51 -3
  220. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +3 -0
  221. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +18 -8
  222. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +3 -0
  223. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentDescriptor.h +6 -8
  224. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +56 -7
  225. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +8 -0
  226. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +3 -2
  227. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +9 -3
  228. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +1 -1
  229. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +35 -0
  230. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +7 -0
  231. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -1
  232. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +12 -12
  233. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +4 -4
  234. package/Microsoft.ReactNative/Fabric/ImageRequest.cpp +4 -8
  235. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp +16 -15
  236. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewTraitsInitializer.h +1 -5
  237. package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +26 -0
  238. package/Microsoft.ReactNative/IReactViewComponentBuilder.idl +1 -1
  239. package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp +15 -0
  240. package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.h +9 -0
  241. package/Microsoft.ReactNative/ReactHost/ReactHost.cpp +20 -1
  242. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +11 -6
  243. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +1 -1
  244. package/Microsoft.ReactNative/ReactNativeIsland.idl +3 -2
  245. package/Microsoft.ReactNative/SynchronousEventBeat.cpp +14 -4
  246. package/Microsoft.ReactNative/SynchronousEventBeat.h +4 -2
  247. package/Microsoft.ReactNative/ViewProps.idl +2 -0
  248. package/Microsoft.ReactNative.Cxx/ApiLoaders/JSRuntimeApi.cpp +78 -0
  249. package/Microsoft.ReactNative.Cxx/ApiLoaders/JSRuntimeApi.h +51 -0
  250. package/Microsoft.ReactNative.Cxx/ApiLoaders/JSRuntimeApi.inc +48 -0
  251. package/Microsoft.ReactNative.Cxx/ApiLoaders/NodeApi.cpp +41 -0
  252. package/Microsoft.ReactNative.Cxx/ApiLoaders/NodeApi.h +127 -0
  253. package/Microsoft.ReactNative.Cxx/ApiLoaders/NodeApi.inc +125 -0
  254. package/Microsoft.ReactNative.Cxx/ApiLoaders/NodeApi_posix.cpp +16 -0
  255. package/Microsoft.ReactNative.Cxx/ApiLoaders/NodeApi_win.cpp +23 -0
  256. package/Microsoft.ReactNative.Cxx/ComponentView.Experimental.interop.h +14 -0
  257. package/Microsoft.ReactNative.Cxx/JSI/decorator.h +834 -0
  258. package/Microsoft.ReactNative.Cxx/JSI/instrumentation.h +117 -0
  259. package/Microsoft.ReactNative.Cxx/JSI/jsi-inl.h +366 -0
  260. package/Microsoft.ReactNative.Cxx/JSI/jsi.cpp +560 -0
  261. package/Microsoft.ReactNative.Cxx/JSI/jsi.h +1611 -0
  262. package/Microsoft.ReactNative.Cxx/JSI/threadsafe.h +79 -0
  263. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +7 -11
  264. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems.filters +1 -1
  265. package/Microsoft.ReactNative.Cxx/NodeApiJsiRuntime.cpp +2878 -0
  266. package/Microsoft.ReactNative.Cxx/NodeApiJsiRuntime.h +36 -0
  267. package/Microsoft.ReactNative.Cxx/ReactCommon/CallInvoker.h +64 -0
  268. package/Microsoft.ReactNative.Cxx/ReactCommon/SchedulerPriority.h +22 -0
  269. package/{ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core → Microsoft.ReactNative.Cxx}/ReactCommon/TurboModule.cpp +63 -63
  270. package/Microsoft.ReactNative.Cxx/ReactCommon/TurboModule.h +165 -0
  271. package/Microsoft.ReactNative.Cxx/ReactCommon/TurboModuleUtils.cpp +105 -0
  272. package/{ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core → Microsoft.ReactNative.Cxx}/ReactCommon/TurboModuleUtils.h +57 -58
  273. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/AString.h +42 -0
  274. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Array.h +151 -0
  275. package/{ReactCommon/TEMP_UntilReactCommonUpdate → Microsoft.ReactNative.Cxx/ReactCommon}/react/bridging/Base.h +177 -154
  276. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Bool.h +25 -0
  277. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Bridging.h +21 -0
  278. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/CallbackWrapper.h +67 -0
  279. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Class.h +90 -0
  280. package/{ReactCommon/TEMP_UntilReactCommonUpdate → Microsoft.ReactNative.Cxx/ReactCommon}/react/bridging/Convert.h +170 -172
  281. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Error.h +51 -0
  282. package/{ReactCommon/TEMP_UntilReactCommonUpdate → Microsoft.ReactNative.Cxx/ReactCommon}/react/bridging/EventEmitter.h +134 -136
  283. package/{ReactCommon/TEMP_UntilReactCommonUpdate → Microsoft.ReactNative.Cxx/ReactCommon}/react/bridging/Function.h +283 -283
  284. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/LongLivedObject.cpp +63 -0
  285. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/LongLivedObject.h +61 -0
  286. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Object.h +93 -0
  287. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Promise.h +104 -0
  288. package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Value.h +107 -0
  289. package/Microsoft.ReactNative.Cxx/ReactCommon/react/debug/flags.h +22 -0
  290. package/Microsoft.ReactNative.Cxx/ReactCommon/react/debug/react_native_assert.h +72 -0
  291. package/Microsoft.ReactNative.Cxx/node-api/js_native_api.h +553 -0
  292. package/Microsoft.ReactNative.Cxx/node-api/js_native_api_types.h +167 -0
  293. package/Microsoft.ReactNative.Cxx/node-api/js_runtime_api.h +186 -0
  294. package/Microsoft.ReactNative.Cxx/stubs/glog/logging.h +82 -0
  295. package/PropertySheets/Bundle.Common.targets +1 -1
  296. package/PropertySheets/Bundle.props +3 -0
  297. package/PropertySheets/Generated/PackageVersion.g.props +4 -4
  298. package/PropertySheets/ManagedCodeGen/Microsoft.ReactNative.Managed.CodeGen.targets +1 -1
  299. package/PropertySheets/OutputMSBuildProperties.targets +3 -1
  300. package/ReactCommon/ReactCommon.vcxproj +5 -0
  301. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.cpp +2 -3
  302. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/test/testlib.cpp +61 -0
  303. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModule.h +26 -23
  304. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +150 -0
  305. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/AccessibilityPrimitives.h +252 -0
  306. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/accessibilityPropsConversions.h +795 -0
  307. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/runtimescheduler/SchedulerPriorityUtils.h +59 -0
  308. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp +188 -39
  309. package/Scripts/Microsoft.ReactNative.Managed.CodeGen.targets +1 -1
  310. package/Scripts/Tfs/Layout-MSRN-Headers.ps1 +97 -62
  311. package/Shared/InspectorPackagerConnection.cpp +3 -6
  312. package/Shared/InspectorPackagerConnection.h +2 -2
  313. package/Shared/InstanceManager.h +1 -1
  314. package/Shared/OInstance.h +1 -1
  315. package/Shared/Shared.vcxitems +20 -2
  316. package/Shared/Shared.vcxitems.filters +4 -1
  317. package/Shared/TurboModuleManager.cpp +29 -4
  318. package/codegen/NativeAccessibilityInfoSpec.g.h +28 -9
  319. package/codegen/NativeAccessibilityManagerSpec.g.h +20 -13
  320. package/codegen/NativeActionSheetManagerSpec.g.h +5 -0
  321. package/codegen/NativeAlertManagerSpec.g.h +1 -0
  322. package/codegen/NativeAnimatedModuleSpec.g.h +1 -0
  323. package/codegen/NativeAnimatedTurboModuleSpec.g.h +1 -0
  324. package/codegen/NativeAppStateSpec.g.h +1 -0
  325. package/codegen/NativeAppThemeSpec.g.h +1 -0
  326. package/codegen/NativeAppearanceSpec.g.h +1 -0
  327. package/codegen/NativeBlobModuleSpec.g.h +1 -0
  328. package/codegen/NativeBugReportingSpec.g.h +1 -0
  329. package/codegen/NativeClipboardSpec.g.h +1 -0
  330. package/codegen/NativeDOMSpec.g.h +1 -0
  331. package/codegen/NativeDevLoadingViewSpec.g.h +1 -0
  332. package/codegen/NativeDevMenuSpec.g.h +1 -0
  333. package/codegen/NativeDevSettingsSpec.g.h +1 -0
  334. package/codegen/NativeDeviceEventManagerSpec.g.h +1 -0
  335. package/codegen/NativeDeviceInfoSpec.g.h +1 -0
  336. package/codegen/NativeDialogManagerAndroidSpec.g.h +1 -0
  337. package/codegen/NativeDialogManagerWindowsSpec.g.h +1 -0
  338. package/codegen/NativeExceptionsManagerSpec.g.h +2 -7
  339. package/codegen/NativeFileReaderModuleSpec.g.h +1 -0
  340. package/codegen/NativeFrameRateLoggerSpec.g.h +1 -0
  341. package/codegen/NativeHeadlessJsTaskSupportSpec.g.h +1 -0
  342. package/codegen/NativeI18nManagerSpec.g.h +1 -0
  343. package/codegen/NativeIdleCallbacksSpec.g.h +1 -0
  344. package/codegen/NativeImageEditorSpec.g.h +1 -0
  345. package/codegen/NativeImageLoaderAndroidSpec.g.h +1 -0
  346. package/codegen/NativeImageLoaderIOSSpec.g.h +1 -0
  347. package/codegen/NativeImageStoreAndroidSpec.g.h +1 -0
  348. package/codegen/NativeImageStoreIOSSpec.g.h +1 -0
  349. package/codegen/NativeIntentAndroidSpec.g.h +1 -0
  350. package/codegen/NativeIntersectionObserverSpec.g.h +3 -0
  351. package/codegen/NativeJSCHeapCaptureSpec.g.h +1 -0
  352. package/codegen/NativeJSCSamplingProfilerSpec.g.h +1 -0
  353. package/codegen/NativeKeyboardObserverSpec.g.h +1 -0
  354. package/codegen/NativeLinkingManagerSpec.g.h +1 -0
  355. package/codegen/NativeLogBoxSpec.g.h +1 -0
  356. package/codegen/NativeMicrotasksSpec.g.h +1 -0
  357. package/codegen/NativeModalManagerSpec.g.h +1 -0
  358. package/codegen/NativeMutationObserverSpec.g.h +1 -0
  359. package/codegen/NativeNetworkingAndroidSpec.g.h +1 -0
  360. package/codegen/NativeNetworkingIOSSpec.g.h +1 -0
  361. package/codegen/NativePerformanceSpec.g.h +128 -3
  362. package/codegen/NativePermissionsAndroidSpec.g.h +1 -0
  363. package/codegen/NativePlatformConstantsAndroidSpec.g.h +1 -0
  364. package/codegen/NativePlatformConstantsIOSSpec.g.h +1 -0
  365. package/codegen/NativePlatformConstantsWindowsSpec.g.h +1 -0
  366. package/codegen/NativePushNotificationManagerIOSSpec.g.h +1 -0
  367. package/codegen/NativeReactDevToolsRuntimeSettingsModuleSpec.g.h +67 -0
  368. package/codegen/NativeReactDevToolsSettingsManagerSpec.g.h +41 -0
  369. package/codegen/NativeReactNativeFeatureFlagsSpec.g.h +126 -137
  370. package/codegen/NativeRedBoxSpec.g.h +1 -0
  371. package/codegen/NativeSampleTurboModuleSpec.g.h +1 -0
  372. package/codegen/NativeSegmentFetcherSpec.g.h +1 -0
  373. package/codegen/NativeSettingsManagerSpec.g.h +1 -0
  374. package/codegen/NativeShareModuleSpec.g.h +1 -0
  375. package/codegen/NativeSoundManagerSpec.g.h +1 -0
  376. package/codegen/NativeSourceCodeSpec.g.h +1 -0
  377. package/codegen/NativeStatusBarManagerAndroidSpec.g.h +1 -0
  378. package/codegen/NativeStatusBarManagerIOSSpec.g.h +1 -0
  379. package/codegen/NativeTimingSpec.g.h +1 -0
  380. package/codegen/NativeToastAndroidSpec.g.h +1 -0
  381. package/codegen/NativeUIManagerSpec.g.h +1 -0
  382. package/codegen/NativeVibrationSpec.g.h +1 -0
  383. package/codegen/NativeWebSocketModuleSpec.g.h +1 -0
  384. package/codegen/react/components/rnwcore/ComponentDescriptors.h +0 -1
  385. package/codegen/react/components/rnwcore/Props.cpp +1 -0
  386. package/codegen/react/components/rnwcore/Props.h +1 -0
  387. package/codegen/react/components/rnwcore/ShadowNodes.cpp +0 -1
  388. package/codegen/react/components/rnwcore/ShadowNodes.h +0 -11
  389. package/codegen/react/components/rnwcore/States.h +0 -12
  390. package/codegen/rnwcoreJSI-generated.cpp +219 -186
  391. package/codegen/rnwcoreJSI.h +942 -511
  392. package/index.js +10 -3
  393. package/index.windows.js +10 -3
  394. package/jest/setup.js +36 -1
  395. package/just-task.js +15 -0
  396. package/package.json +22 -22
  397. package/src/private/animated/NativeAnimatedHelper.js +18 -16
  398. package/src/private/animated/useAnimatedPropsMemo.js +348 -0
  399. package/src/private/animated/useAnimatedPropsMemo.windows.js +356 -0
  400. package/src/private/components/HScrollViewNativeComponents.js +1 -27
  401. package/src/private/components/SafeAreaView_INTERNAL_DO_NOT_USE.js +11 -8
  402. package/src/private/components/VScrollViewNativeComponents.js +2 -25
  403. package/src/private/debugging/ReactDevToolsSettingsManager.android.js +20 -0
  404. package/src/private/debugging/ReactDevToolsSettingsManager.ios.js +30 -0
  405. package/src/private/debugging/ReactDevToolsSettingsManager.windows.js +20 -0
  406. package/src/private/{fusebox → debugging}/setUpFuseboxReactDevToolsDispatcher.js +6 -0
  407. package/src/private/devmenu/DevMenu.d.ts +20 -0
  408. package/src/private/devmenu/DevMenu.js +31 -0
  409. package/src/private/featureflags/ReactNativeFeatureFlags.js +95 -86
  410. package/src/private/featureflags/ReactNativeFeatureFlagsBase.js +8 -2
  411. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +17 -19
  412. package/src/private/fusebox/specs/NativeReactDevToolsRuntimeSettingsModule.js +34 -0
  413. package/src/private/setup/setUpDOM.js +14 -6
  414. package/src/private/setup/setUpMutationObserver.js +5 -0
  415. package/src/private/specs/components/AndroidHorizontalScrollContentViewNativeComponent.js +1 -0
  416. package/src/private/specs/components/RCTModalHostViewNativeComponent.js +8 -0
  417. package/src/private/specs/modules/NativeAccessibilityInfo.js +9 -0
  418. package/src/private/specs/modules/NativeAccessibilityManager.js +4 -0
  419. package/src/private/specs/modules/NativeActionSheetManager.js +2 -0
  420. package/src/private/specs/modules/NativeAppearance.js +4 -10
  421. package/src/private/specs/modules/NativeExceptionsManager.js +0 -12
  422. package/src/private/specs/modules/{NativeDevToolsSettingsManager.js → NativeReactDevToolsSettingsManager.js} +3 -5
  423. package/src/private/webapis/dom/geometry/DOMRect.js +2 -2
  424. package/src/private/webapis/dom/geometry/DOMRectReadOnly.js +2 -2
  425. package/src/private/webapis/dom/nodes/ReactNativeElement.js +2 -3
  426. package/src/private/webapis/intersectionobserver/IntersectionObserver.js +102 -11
  427. package/src/private/webapis/intersectionobserver/IntersectionObserverEntry.js +26 -0
  428. package/src/private/webapis/intersectionobserver/IntersectionObserverManager.js +1 -0
  429. package/src/private/webapis/intersectionobserver/specs/NativeIntersectionObserver.js +1 -0
  430. package/src/private/webapis/intersectionobserver/specs/__mocks__/NativeIntersectionObserver.js +9 -0
  431. package/src/private/webapis/performance/EventTiming.js +13 -8
  432. package/src/private/webapis/performance/Performance.js +66 -73
  433. package/src/private/webapis/performance/PerformanceEntry.js +2 -5
  434. package/src/private/webapis/performance/PerformanceObserver.js +65 -164
  435. package/src/private/webapis/performance/RawPerformanceEntry.js +1 -1
  436. package/src/private/webapis/performance/UserTiming.js +11 -7
  437. package/src/private/webapis/performance/Utilities.js +18 -0
  438. package/src/private/webapis/performance/specs/NativePerformance.js +71 -2
  439. package/src/private/webapis/performance/specs/__mocks__/NativePerformanceMock.js +267 -0
  440. package/templates/cpp-lib/template.config.js +13 -7
  441. package/templates/templateUtils.js +10 -0
  442. package/types/index.d.ts +1 -1
  443. package/types/public/ReactNativeTypes.d.ts +4 -8
  444. package/Libraries/DevToolsSettings/DevToolsSettingsManager.android.js +0 -35
  445. package/Libraries/DevToolsSettings/DevToolsSettingsManager.d.ts +0 -20
  446. package/Libraries/DevToolsSettings/DevToolsSettingsManager.ios.js +0 -49
  447. package/Libraries/DevToolsSettings/DevToolsSettingsManager.windows.js +0 -35
  448. package/Libraries/DevToolsSettings/NativeDevToolsSettingsManager.js +0 -13
  449. package/Libraries/ReactNative/ReactFabricInternals.js +0 -17
  450. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/bridging/CallbackWrapper.h +0 -101
  451. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/scrollview/ScrollViewProps.cpp +0 -569
  452. package/codegen/NativeDevToolsSettingsManagerSpec.g.h +0 -52
  453. package/codegen/NativePerformanceObserverSpec.g.h +0 -130
  454. package/src/private/components/useSyncOnScroll.js +0 -48
  455. package/src/private/webapis/performance/specs/NativePerformanceObserver.js +0 -61
  456. package/src/private/webapis/performance/specs/__mocks__/NativePerformance.js +0 -67
  457. package/src/private/webapis/performance/specs/__mocks__/NativePerformanceObserver.js +0 -127
  458. package/types/experimental.d.ts +0 -59
  459. /package/src/private/{fusebox → debugging}/FuseboxSessionObserver.js +0 -0
@@ -32,16 +32,32 @@
32
32
 
33
33
  namespace winrt::Microsoft::ReactNative::Composition::implementation {
34
34
 
35
+ constexpr float FOCUS_VISUAL_WIDTH = 2.0f;
36
+
37
+ // m_outerVisual
38
+ // |
39
+ // |
40
+ // ----- m_visual <-- Background / clip - Can be a custom visual depending on Component type
41
+ // |
42
+ // ----- Border Visuals x N (BorderPrimitive attached to m_visual)
43
+ // ------Focus Visual Container (created when hosting focus visuals)
44
+ // |
45
+ // |------Inner Focus Visual
46
+ // |
47
+ // ------ Border Visuals x N (BorderPrimitive)
48
+ // |------Outer Focus Visual
49
+ // |
50
+ // ------ Border Visuals x N (BorderPrimitive)
51
+
35
52
  ComponentView::ComponentView(
36
53
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
37
54
  facebook::react::Tag tag,
38
55
  winrt::Microsoft::ReactNative::ReactContext const &reactContext,
39
- ComponentViewFeatures flags)
40
- : base_type(tag, reactContext), m_compContext(compContext), m_flags(flags) {
56
+ ComponentViewFeatures flags,
57
+ winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder)
58
+ : base_type(tag, reactContext, builder), m_compContext(compContext), m_flags(flags) {
41
59
  m_outerVisual = compContext.CreateSpriteVisual(); // TODO could be a raw ContainerVisual if we had a
42
60
  // CreateContainerVisual in ICompositionContext
43
- m_focusVisual = compContext.CreateFocusVisual();
44
- m_outerVisual.InsertAt(m_focusVisual.InnerVisual(), 0);
45
61
  }
46
62
 
47
63
  ComponentView::~ComponentView() {
@@ -68,9 +84,21 @@ void ComponentView::onThemeChanged() noexcept {
68
84
  }
69
85
  }
70
86
 
71
- if ((m_flags & ComponentViewFeatures::NativeBorder) == ComponentViewFeatures::NativeBorder) {
72
- m_needsBorderUpdate = true;
73
- finalizeBorderUpdates(m_layoutMetrics, *viewProps());
87
+ if (m_borderPrimitive) {
88
+ m_borderPrimitive->onThemeChanged(
89
+ m_layoutMetrics, BorderPrimitive::resolveAndAlignBorderMetrics(m_layoutMetrics, *viewProps()));
90
+ }
91
+ if (m_componentHostingFocusVisual) {
92
+ if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive) {
93
+ auto innerFocusMetrics = focusLayoutMetrics(true /*inner*/);
94
+ m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive->onThemeChanged(
95
+ innerFocusMetrics, focusBorderMetrics(true /*inner*/, innerFocusMetrics));
96
+ }
97
+ if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive) {
98
+ auto outerFocusMetrics = focusLayoutMetrics(true /*inner*/);
99
+ m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive->onThemeChanged(
100
+ outerFocusMetrics, focusBorderMetrics(false /*inner*/, outerFocusMetrics));
101
+ }
74
102
  }
75
103
 
76
104
  if ((m_flags & ComponentViewFeatures::ShadowProps) == ComponentViewFeatures::ShadowProps) {
@@ -131,13 +159,25 @@ void ComponentView::updateProps(
131
159
  }
132
160
  }
133
161
 
134
- if ((m_flags & ComponentViewFeatures::NativeBorder) == ComponentViewFeatures::NativeBorder) {
135
- updateBorderProps(oldViewProps, newViewProps);
162
+ if (m_borderPrimitive) {
163
+ m_borderPrimitive->updateProps(oldViewProps, newViewProps);
164
+ }
165
+
166
+ if (m_componentHostingFocusVisual) {
167
+ if (!newViewProps.enableFocusRing) {
168
+ m_componentHostingFocusVisual->hostFocusVisual(false, get_strong());
169
+ }
170
+
171
+ if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive) {
172
+ m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive->updateProps(oldViewProps, newViewProps);
173
+ }
174
+ if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive) {
175
+ m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive->updateProps(oldViewProps, newViewProps);
176
+ }
136
177
  }
137
178
  if ((m_flags & ComponentViewFeatures::ShadowProps) == ComponentViewFeatures::ShadowProps) {
138
179
  updateShadowProps(oldViewProps, newViewProps);
139
180
  }
140
-
141
181
  if (oldViewProps.tooltip != newViewProps.tooltip) {
142
182
  if (!m_tooltipTracked && newViewProps.tooltip) {
143
183
  TooltipService::GetCurrent(m_reactContext.Properties())->StartTracking(*this);
@@ -155,13 +195,84 @@ void ComponentView::updateLayoutMetrics(
155
195
  facebook::react::LayoutMetrics const &layoutMetrics,
156
196
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept {
157
197
  if ((m_flags & ComponentViewFeatures::NativeBorder) == ComponentViewFeatures::NativeBorder) {
158
- updateBorderLayoutMetrics(layoutMetrics, *viewProps());
198
+ updateClippingPath(layoutMetrics, *viewProps());
199
+ OuterVisual().Size(
200
+ {layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor,
201
+ layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor});
202
+ OuterVisual().Offset({
203
+ layoutMetrics.frame.origin.x * layoutMetrics.pointScaleFactor,
204
+ layoutMetrics.frame.origin.y * layoutMetrics.pointScaleFactor,
205
+ 0.0f,
206
+ });
159
207
  }
160
208
 
161
209
  base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
210
+
211
+ if (layoutMetrics != oldLayoutMetrics) {
212
+ if (m_borderPrimitive) {
213
+ m_borderPrimitive->markNeedsUpdate();
214
+ }
215
+
216
+ if (m_componentHostingFocusVisual) {
217
+ m_componentHostingFocusVisual->updateFocusLayoutMetrics();
218
+ }
219
+ }
220
+
162
221
  UpdateCenterPropertySet();
163
222
  }
164
223
 
224
+ void ComponentView::updateFocusLayoutMetrics() noexcept {
225
+ facebook::react::RectangleEdges<bool> nudgeEdges;
226
+ auto scaleFactor = m_focusPrimitive->m_focusVisualComponent->m_layoutMetrics.pointScaleFactor;
227
+ if (m_focusPrimitive) {
228
+ if (m_focusPrimitive->m_focusOuterPrimitive) {
229
+ auto outerFocusMetrics = m_focusPrimitive->m_focusVisualComponent->focusLayoutMetrics(false /*inner*/);
230
+
231
+ if (outerFocusMetrics.frame.origin.x < 0) {
232
+ nudgeEdges.left = true;
233
+ }
234
+ if (outerFocusMetrics.frame.origin.y < 0) {
235
+ nudgeEdges.top = true;
236
+ }
237
+ if (outerFocusMetrics.frame.getMaxX() > m_layoutMetrics.frame.getMaxX()) {
238
+ nudgeEdges.right = true;
239
+ }
240
+ if (outerFocusMetrics.frame.getMaxY() > m_layoutMetrics.frame.getMaxY()) {
241
+ nudgeEdges.bottom = true;
242
+ }
243
+
244
+ m_focusPrimitive->m_focusOuterPrimitive->RootVisual().Size(
245
+ {outerFocusMetrics.frame.size.width * scaleFactor -
246
+ (nudgeEdges.left ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0) -
247
+ (nudgeEdges.right ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0),
248
+ outerFocusMetrics.frame.size.height * scaleFactor -
249
+ (nudgeEdges.top ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0) -
250
+ (nudgeEdges.bottom ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0)});
251
+ m_focusPrimitive->m_focusOuterPrimitive->RootVisual().Offset(
252
+ {nudgeEdges.left ? 0 : -(FOCUS_VISUAL_WIDTH * 2 * scaleFactor),
253
+ nudgeEdges.top ? 0 : -(FOCUS_VISUAL_WIDTH * 2 * scaleFactor),
254
+ 0.0f});
255
+ m_focusPrimitive->m_focusOuterPrimitive->markNeedsUpdate();
256
+ }
257
+
258
+ if (m_focusPrimitive->m_focusInnerPrimitive) {
259
+ auto innerFocusMetrics = m_focusPrimitive->m_focusVisualComponent->focusLayoutMetrics(true /*inner*/);
260
+ m_focusPrimitive->m_focusInnerPrimitive->RootVisual().Size(
261
+ {innerFocusMetrics.frame.size.width * scaleFactor -
262
+ (nudgeEdges.left ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0) -
263
+ (nudgeEdges.right ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0),
264
+ innerFocusMetrics.frame.size.height * scaleFactor -
265
+ (nudgeEdges.top ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0) -
266
+ (nudgeEdges.bottom ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0)});
267
+ m_focusPrimitive->m_focusInnerPrimitive->RootVisual().Offset(
268
+ {nudgeEdges.left ? 0 : -FOCUS_VISUAL_WIDTH * scaleFactor,
269
+ nudgeEdges.top ? 0 : -FOCUS_VISUAL_WIDTH * scaleFactor,
270
+ 0.0f});
271
+ m_focusPrimitive->m_focusInnerPrimitive->markNeedsUpdate();
272
+ }
273
+ }
274
+ }
275
+
165
276
  const facebook::react::LayoutMetrics &ComponentView::layoutMetrics() const noexcept {
166
277
  return m_layoutMetrics;
167
278
  }
@@ -199,7 +310,27 @@ void ComponentView::FinalizeTransform(
199
310
 
200
311
  void ComponentView::FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept {
201
312
  if ((m_flags & ComponentViewFeatures::NativeBorder) == ComponentViewFeatures::NativeBorder) {
202
- finalizeBorderUpdates(m_layoutMetrics, *viewProps());
313
+ auto borderMetrics = BorderPrimitive::resolveAndAlignBorderMetrics(m_layoutMetrics, *viewProps());
314
+ if (!m_borderPrimitive && BorderPrimitive::requiresBorder(borderMetrics, theme())) {
315
+ m_borderPrimitive = std::make_shared<BorderPrimitive>(*this, Visual());
316
+ }
317
+
318
+ if (m_borderPrimitive) {
319
+ m_borderPrimitive->finalize(m_layoutMetrics, borderMetrics);
320
+ }
321
+ }
322
+
323
+ if (m_componentHostingFocusVisual) {
324
+ if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive) {
325
+ auto innerFocusMetrics = focusLayoutMetrics(true /*inner*/);
326
+ m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive->finalize(
327
+ innerFocusMetrics, focusBorderMetrics(true /*inner*/, innerFocusMetrics));
328
+ }
329
+ if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive) {
330
+ auto outerFocusMetrics = focusLayoutMetrics(false /*inner*/);
331
+ m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive->finalize(
332
+ outerFocusMetrics, focusBorderMetrics(false /*inner*/, outerFocusMetrics));
333
+ }
203
334
  }
204
335
 
205
336
  if (m_FinalizeTransform) {
@@ -213,7 +344,12 @@ void ComponentView::onLostFocus(
213
344
  const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
214
345
  if (args.OriginalSource() == Tag()) {
215
346
  m_eventEmitter->onBlur();
216
- showFocusVisual(false);
347
+
348
+ if (m_componentHostingFocusVisual) {
349
+ auto s = get_strong();
350
+
351
+ m_componentHostingFocusVisual->hostFocusVisual(false, get_strong());
352
+ }
217
353
  if (m_uiaProvider) {
218
354
  winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
219
355
  m_uiaProvider, UIA_HasKeyboardFocusPropertyId, true, false);
@@ -222,12 +358,47 @@ void ComponentView::onLostFocus(
222
358
  base_type::onLostFocus(args);
223
359
  }
224
360
 
361
+ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ComponentView::visualToHostFocus() noexcept {
362
+ return OuterVisual();
363
+ }
364
+
365
+ // We want to host focus visuals as close to the focused component as possible. However since the focus visuals extend
366
+ // past the bounds of the component, in cases where additional components are positioned directly next to this one, we'd
367
+ // get zorder issues causing most of the focus rect to be obscured. So we go up the tree until we find a component who's
368
+ // bounds will fix the entire focus rect.
369
+ winrt::com_ptr<ComponentView> ComponentView::focusVisualRoot(const facebook::react::Rect &focusRect) noexcept {
370
+ auto compVisual =
371
+ winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(OuterVisual());
372
+ if (!compVisual) {
373
+ return get_strong();
374
+ // When not using lifted composition, force the focus visual to host within its own component, as we do not support
375
+ // ParentForTransform
376
+ }
377
+
378
+ if (facebook::react::Rect::intersect(focusRect, m_layoutMetrics.frame) == focusRect) {
379
+ return get_strong();
380
+ }
381
+
382
+ if (!m_parent) {
383
+ return get_strong();
384
+ }
385
+
386
+ return m_parent.as<ComponentView>()->focusVisualRoot(
387
+ {{focusRect.origin.x + m_layoutMetrics.frame.origin.x, focusRect.origin.y + m_layoutMetrics.frame.origin.y},
388
+ focusRect.size});
389
+ }
390
+
225
391
  void ComponentView::onGotFocus(
226
392
  const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
227
393
  if (args.OriginalSource() == Tag()) {
228
394
  m_eventEmitter->onFocus();
229
- if (m_enableFocusVisual) {
230
- showFocusVisual(true);
395
+ if (viewProps()->enableFocusRing) {
396
+ facebook::react::Rect focusRect = m_layoutMetrics.frame;
397
+ focusRect.origin.x -= (FOCUS_VISUAL_WIDTH * 2);
398
+ focusRect.origin.y -= (FOCUS_VISUAL_WIDTH * 2);
399
+ focusRect.size.width += (FOCUS_VISUAL_WIDTH * 2);
400
+ focusRect.size.height += (FOCUS_VISUAL_WIDTH * 2);
401
+ focusVisualRoot(focusRect)->hostFocusVisual(true, get_strong());
231
402
  }
232
403
  if (m_uiaProvider) {
233
404
  auto spProviderSimple = m_uiaProvider.try_as<IRawElementProviderSimple>();
@@ -325,6 +496,10 @@ void ComponentView::ReleasePointerCapture(
325
496
  ->ReleasePointerCapture(pointer, static_cast<facebook::react::Tag>(Tag()));
326
497
  }
327
498
 
499
+ void ComponentView::SetViewFeatures(ComponentViewFeatures viewFeatures) noexcept {
500
+ m_flags = viewFeatures;
501
+ }
502
+
328
503
  RECT ComponentView::getClientRect() const noexcept {
329
504
  RECT rc{0};
330
505
  facebook::react::Point parentOffset{0};
@@ -356,907 +531,146 @@ const facebook::react::SharedViewEventEmitter &ComponentView::GetEventEmitter()
356
531
  return m_eventEmitter;
357
532
  }
358
533
 
359
- std::array<
360
- winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual,
361
- ComponentView::SpecialBorderLayerCount>
362
- ComponentView::FindSpecialBorderLayers() const noexcept {
363
- std::array<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual, SpecialBorderLayerCount> layers{
364
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
365
-
366
- if (m_numBorderVisuals) {
367
- for (uint8_t i = 0; i < m_numBorderVisuals; i++) {
368
- auto visual = Visual().GetAt(i);
369
- layers[i] = visual.as<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual>();
370
- }
371
- }
372
-
373
- return layers;
374
- }
375
-
376
- struct RoundedPathParameters {
377
- float topLeftRadiusX = 0;
378
- float topLeftRadiusY = 0;
379
- float topRightRadiusX = 0;
380
- float topRightRadiusY = 0;
381
- float bottomRightRadiusX = 0;
382
- float bottomRightRadiusY = 0;
383
- float bottomLeftRadiusX = 0;
384
- float bottomLeftRadiusY = 0;
385
- };
386
-
387
- /*
388
- * Creates and returns a PathGeometry object used to clip the visuals of an element when a BorderRadius is set.
389
- * Can also be used as part of a GeometryGroup for drawing a rounded border / innerstroke when called from
390
- * GetGeometryForRoundedBorder. "params" defines the radii (horizontal and vertical) for each corner (top left, top
391
- * right, bottom right, bottom left). "rectPathGeometry" defines the bounding box of the generated shape.
392
- */
393
- static winrt::com_ptr<ID2D1PathGeometry> GenerateRoundedRectPathGeometry(
394
- winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
395
- const RoundedPathParameters &params,
396
- const facebook::react::RectangleEdges<float> &rectPathGeometry) noexcept {
397
- winrt::com_ptr<ID2D1PathGeometry> pathGeometry;
398
- winrt::com_ptr<ID2D1Factory1> spD2dFactory;
399
- compContext.as<::Microsoft::ReactNative::Composition::Experimental::ICompositionContextInterop>()->D2DFactory(
400
- spD2dFactory.put());
401
-
402
- // Create a path geometry.
403
- HRESULT hr = spD2dFactory->CreatePathGeometry(pathGeometry.put());
404
- if (FAILED(hr)) {
405
- assert(false);
406
- return nullptr;
407
- }
408
-
409
- // Write to the path geometry using the geometry sink.
410
- winrt::com_ptr<ID2D1GeometrySink> spSink = nullptr;
411
- hr = pathGeometry->Open(spSink.put());
412
-
413
- if (FAILED(hr)) {
414
- assert(false);
415
- return nullptr;
416
- }
417
-
418
- float left = rectPathGeometry.left;
419
- float right = rectPathGeometry.right;
420
- float top = rectPathGeometry.top;
421
- float bottom = rectPathGeometry.bottom;
422
-
423
- // This function uses Cubic Beziers to approximate Arc segments, even though D2D supports arcs.
424
- // This is INTENTIONAL. D2D Arc Segments are eventually converted into cubic beziers, but this
425
- // is done in such a way that we don't have control over how many bezier curve segments are used
426
- // for each arc. We need to ensure that we always use the same number of control points so that
427
- // our paths can be used in a PathKeyFrameAnimation.
428
- // Value for control point scale factor derived from methods described in:
429
- // https://web.archive.org/web/20200322075504/http://itc.ktu.lt/index.php/ITC/article/download/11812/6479
430
- constexpr float controlPointScaleFactor = 0.44771528244f; // 1 - (4 * (sqrtf(2.0f) - 1) / 3.0f);
431
-
432
- #ifdef DEBUG
433
- // std::sqrtf is not constexpr, so we precalculated this and wrote it in a constexpr form above.
434
- // On debug, we should still check that the values are equivalent, though.
435
- static float calculatedScaleFactor = 1 - (4 * (sqrtf(2.0f) - 1) / 3.0f);
436
- assert(controlPointScaleFactor == calculatedScaleFactor);
437
- #endif // DEBUG
438
-
439
- bool needsConsistentNumberOfControlPoints = true; // VisualVersion::IsUseWinCompClippingRegionEnabled();
440
-
441
- if (needsConsistentNumberOfControlPoints || (params.topLeftRadiusX != 0.0 && params.topLeftRadiusY != 0.0)) {
442
- spSink->BeginFigure(D2D1::Point2F(left + params.topLeftRadiusX, top), D2D1_FIGURE_BEGIN_FILLED);
443
- } else {
444
- spSink->BeginFigure(D2D1::Point2F(left, top), D2D1_FIGURE_BEGIN_FILLED);
445
- }
446
-
447
- // Move to the top right corner
448
- spSink->AddLine(D2D1::Point2F(right - params.topRightRadiusX, top));
449
- if (needsConsistentNumberOfControlPoints) {
450
- D2D1_BEZIER_SEGMENT arcSegmentTopRight = {
451
- D2D1::Point2F(right - controlPointScaleFactor * params.topRightRadiusX, top),
452
- D2D1::Point2F(right, top + controlPointScaleFactor * params.topRightRadiusY),
453
- D2D1::Point2F(right, top + params.topRightRadiusY)};
454
-
455
- spSink->AddBezier(&arcSegmentTopRight);
456
- } else if (params.topRightRadiusX != 0.0 && params.topRightRadiusY != 0.0) {
457
- D2D1_ARC_SEGMENT arcSegmentTopRight = {
458
- D2D1::Point2F(right, top + params.topRightRadiusY),
459
- D2D1::SizeF(params.topRightRadiusX, params.topRightRadiusY),
460
- 0.0f,
461
- D2D1_SWEEP_DIRECTION_CLOCKWISE,
462
- D2D1_ARC_SIZE_SMALL};
463
-
464
- spSink->AddArc(&arcSegmentTopRight);
465
- } else {
466
- spSink->AddLine(D2D1::Point2F(right, top));
467
- }
468
-
469
- // Move to the bottom right corner
470
- spSink->AddLine(D2D1::Point2F(right, bottom - params.bottomRightRadiusY));
471
- if (needsConsistentNumberOfControlPoints) {
472
- D2D1_BEZIER_SEGMENT arcSegmentBottomRight = {
473
- D2D1::Point2F(right, bottom - controlPointScaleFactor * params.bottomRightRadiusY),
474
- D2D1::Point2F(right - controlPointScaleFactor * params.bottomRightRadiusX, bottom),
475
- D2D1::Point2F(right - params.bottomRightRadiusX, bottom)};
476
-
477
- spSink->AddBezier(&arcSegmentBottomRight);
478
- } else if (params.bottomRightRadiusX != 0.0 && params.bottomRightRadiusY != 0.0) {
479
- D2D1_ARC_SEGMENT arcSegmentBottomRight = {
480
- D2D1::Point2F(right - params.bottomRightRadiusX, bottom),
481
- D2D1::SizeF(params.bottomRightRadiusX, params.bottomRightRadiusY),
482
- 0.0f,
483
- D2D1_SWEEP_DIRECTION_CLOCKWISE,
484
- D2D1_ARC_SIZE_SMALL};
485
-
486
- spSink->AddArc(&arcSegmentBottomRight);
487
- } else {
488
- spSink->AddLine(D2D1::Point2F(right, bottom));
489
- }
490
-
491
- // Move to the bottom left corner
492
- spSink->AddLine(D2D1::Point2F(left + params.bottomLeftRadiusX, bottom));
493
- if (needsConsistentNumberOfControlPoints) {
494
- D2D1_BEZIER_SEGMENT arcSegmentBottomLeft = {
495
- D2D1::Point2F(left + controlPointScaleFactor * params.bottomLeftRadiusX, bottom),
496
- D2D1::Point2F(left, bottom - controlPointScaleFactor * params.bottomLeftRadiusY),
497
- D2D1::Point2F(left, bottom - params.bottomLeftRadiusY)};
498
-
499
- spSink->AddBezier(&arcSegmentBottomLeft);
500
- } else if (params.bottomLeftRadiusX != 0.0 && params.bottomLeftRadiusY != 0.0) {
501
- D2D1_ARC_SEGMENT arcSegmentBottomLeft = {
502
- D2D1::Point2F(left, bottom - params.bottomLeftRadiusY),
503
- D2D1::SizeF(params.bottomLeftRadiusX, params.bottomLeftRadiusY),
504
- 0.0f,
505
- D2D1_SWEEP_DIRECTION_CLOCKWISE,
506
- D2D1_ARC_SIZE_SMALL};
507
-
508
- spSink->AddArc(&arcSegmentBottomLeft);
509
- } else {
510
- spSink->AddLine(D2D1::Point2F(left, bottom));
511
- }
512
-
513
- // Move to the top left corner
514
- spSink->AddLine(D2D1::Point2F(left, top + params.topLeftRadiusY));
515
- if (needsConsistentNumberOfControlPoints) {
516
- D2D1_BEZIER_SEGMENT arcSegmentTopLeft = {
517
- D2D1::Point2F(left, top + controlPointScaleFactor * params.topLeftRadiusY),
518
- D2D1::Point2F(left + controlPointScaleFactor * params.topLeftRadiusX, top),
519
- D2D1::Point2F(left + params.topLeftRadiusX, top)};
520
-
521
- spSink->AddBezier(&arcSegmentTopLeft);
522
- } else if (params.topLeftRadiusX != 0.0 && params.topLeftRadiusY != 0.0) {
523
- D2D1_ARC_SEGMENT arcSegmentTopLeft = {
524
- D2D1::Point2F(left + params.topLeftRadiusX, top),
525
- D2D1::SizeF(params.topLeftRadiusX, params.topLeftRadiusY),
526
- 0.0f,
527
- D2D1_SWEEP_DIRECTION_CLOCKWISE,
528
- D2D1_ARC_SIZE_SMALL};
529
-
530
- spSink->AddArc(&arcSegmentTopLeft);
531
- } else {
532
- spSink->AddLine(D2D1::Point2F(left, top));
533
- }
534
-
535
- spSink->EndFigure(D2D1_FIGURE_END_CLOSED);
536
- spSink->Close();
537
-
538
- return pathGeometry;
539
- }
540
-
541
- RoundedPathParameters GenerateRoundedPathParameters(
542
- const facebook::react::RectangleCorners<facebook::react::CornerRadii> &baseRadius,
543
- const facebook::react::RectangleEdges<float> &inset,
544
- const facebook::react::Size &pathSize) noexcept {
545
- RoundedPathParameters result;
546
-
547
- if (pathSize.width == 0 || pathSize.height == 0) {
548
- return result;
549
- }
550
-
551
- float totalTopRadius = baseRadius.topLeft.horizontal + baseRadius.topRight.horizontal;
552
- float totalRightRadius = baseRadius.topRight.vertical + baseRadius.bottomRight.vertical;
553
- float totalBottomRadius = baseRadius.bottomRight.horizontal + baseRadius.bottomLeft.horizontal;
554
- float totalLeftRadius = baseRadius.bottomLeft.vertical + baseRadius.topLeft.vertical;
555
-
556
- float maxHorizontalRadius = std::max(totalTopRadius, totalBottomRadius);
557
- float maxVerticalRadius = std::max(totalLeftRadius, totalRightRadius);
558
-
559
- double totalWidth = inset.left + inset.right + pathSize.width;
560
- double totalHeight = inset.top + inset.bottom + pathSize.height;
561
-
562
- float scaleHoriz = static_cast<float>(maxHorizontalRadius / totalWidth);
563
- float scaleVert = static_cast<float>(maxVerticalRadius / totalHeight);
564
-
565
- float maxScale = std::max(1.0f, std::max(scaleHoriz, scaleVert));
566
-
567
- result.topLeftRadiusX = std::max(0.0f, baseRadius.topLeft.horizontal / maxScale - inset.left);
568
- result.topLeftRadiusY = std::max(0.0f, baseRadius.topLeft.vertical / maxScale - inset.top);
569
- result.topRightRadiusX = std::max(0.0f, baseRadius.topRight.horizontal / maxScale - inset.right);
570
- result.topRightRadiusY = std::max(0.0f, baseRadius.topRight.vertical / maxScale - inset.top);
571
- result.bottomRightRadiusX = std::max(0.0f, baseRadius.bottomRight.horizontal / maxScale - inset.right);
572
- result.bottomRightRadiusY = std::max(0.0f, baseRadius.bottomRight.vertical / maxScale - inset.bottom);
573
- result.bottomLeftRadiusX = std::max(0.0f, baseRadius.bottomLeft.horizontal / maxScale - inset.left);
574
- result.bottomLeftRadiusY = std::max(0.0f, baseRadius.bottomLeft.vertical / maxScale - inset.bottom);
575
-
576
- return result;
577
- }
578
-
579
- static winrt::com_ptr<ID2D1PathGeometry> GenerateRoundedRectPathGeometry(
580
- winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
581
- const facebook::react::RectangleCorners<facebook::react::CornerRadii> &baseRadius,
582
- const facebook::react::RectangleEdges<float> &inset,
583
- const facebook::react::RectangleEdges<float> &rectPathGeometry) noexcept {
584
- RoundedPathParameters params = GenerateRoundedPathParameters(
585
- baseRadius,
586
- inset,
587
- {rectPathGeometry.right - rectPathGeometry.left, rectPathGeometry.bottom - rectPathGeometry.top});
588
-
589
- return GenerateRoundedRectPathGeometry(compContext, params, rectPathGeometry);
590
- }
591
-
592
- void DrawShape(
593
- ID2D1RenderTarget *pRT,
594
- const D2D1_RECT_F &rect,
595
- ID2D1Brush *brush,
596
- FLOAT strokeWidth,
597
- ID2D1StrokeStyle *strokeStyle) {
598
- pRT->DrawRectangle(rect, brush, strokeWidth, strokeStyle);
599
- }
600
-
601
- void DrawShape(ID2D1RenderTarget *pRT, ID2D1GeometryGroup &geometry, ID2D1Brush *brush, FLOAT, ID2D1StrokeStyle *) {
602
- pRT->FillGeometry(&geometry, brush);
603
- }
604
-
605
- void DrawShape(
606
- ID2D1RenderTarget *pRT,
607
- ID2D1PathGeometry &geometry,
608
- ID2D1Brush *brush,
609
- FLOAT strokeWidth,
610
- ID2D1StrokeStyle *strokeStyle) {
611
- pRT->DrawGeometry(&geometry, brush, strokeWidth, strokeStyle);
612
- }
613
-
614
- template <typename TShape>
615
- void SetBorderLayerPropertiesCommon(
616
- winrt::Microsoft::ReactNative::Composition::implementation::Theme *theme,
617
- winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
618
- winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual &layer,
619
- TShape &shape,
620
- winrt::com_ptr<::Microsoft::ReactNative::Composition::Experimental::ICompositionDrawingSurfaceInterop>
621
- &borderTexture,
622
- const D2D1_RECT_F &textureRect,
623
- facebook::react::Point anchorPoint,
624
- facebook::react::Point anchorOffset,
625
- winrt::Windows::Foundation::Numerics::float2 size,
626
- winrt::Windows::Foundation::Numerics::float2 relativeSizeAdjustment,
627
- FLOAT strokeWidth,
628
- const facebook::react::SharedColor &borderColor,
629
- facebook::react::BorderStyle borderStyle) {
630
- layer.Offset({anchorOffset.x, anchorOffset.y, 0}, {anchorPoint.x, anchorPoint.y, 0});
631
- layer.RelativeSizeWithOffset(size, relativeSizeAdjustment);
632
- layer.as<::Microsoft::ReactNative::Composition::Experimental::IVisualInterop>()->SetClippingPath(nullptr);
633
-
634
- if ((textureRect.right - textureRect.left) <= 0 || (textureRect.bottom - textureRect.top) <= 0)
635
- return;
636
-
637
- auto surface = compContext.CreateDrawingSurfaceBrush(
638
- {(textureRect.right - textureRect.left), (textureRect.bottom - textureRect.top)},
639
- winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
640
- winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
641
- surface.as(borderTexture);
642
-
643
- layer.Brush(surface);
644
-
645
- POINT offset;
646
- ::Microsoft::ReactNative::Composition::AutoDrawDrawingSurface autoDraw(
647
- surface, 1.0f /* We have already done the dpi scaling */, &offset);
648
- if (auto pRT = autoDraw.GetRenderTarget()) {
649
- // Clear with transparency
650
- pRT->Clear();
651
-
652
- if (!facebook::react::isColorMeaningful(borderColor)) {
653
- return;
654
- }
655
-
656
- winrt::com_ptr<ID2D1Factory> spFactory;
657
- pRT->GetFactory(spFactory.put());
658
- assert(spFactory);
659
- if (spFactory == nullptr)
660
- return;
661
-
662
- winrt::com_ptr<ID2D1SolidColorBrush> spBorderBrush;
663
- pRT->CreateSolidColorBrush(theme->D2DColor(*borderColor), spBorderBrush.put());
664
- assert(spBorderBrush);
665
- if (spBorderBrush == nullptr)
666
- return;
667
-
668
- winrt::com_ptr<ID2D1StrokeStyle> spStrokeStyle;
669
-
670
- enum class BorderStyle { Solid, Dotted, Dashed };
671
-
672
- if (borderStyle == facebook::react::BorderStyle::Dotted || borderStyle == facebook::react::BorderStyle::Dashed) {
673
- const auto capStyle =
674
- borderStyle == facebook::react::BorderStyle::Dashed ? D2D1_CAP_STYLE_FLAT : D2D1_CAP_STYLE_ROUND;
675
- const auto strokeStyleProps = D2D1::StrokeStyleProperties(
676
- capStyle,
677
- capStyle,
678
- capStyle,
679
- D2D1_LINE_JOIN_MITER,
680
- 10.0f,
681
- borderStyle == facebook::react::BorderStyle::Dashed ? D2D1_DASH_STYLE_DASH : D2D1_DASH_STYLE_DOT,
682
- 0.0f);
683
- spFactory->CreateStrokeStyle(&strokeStyleProps, nullptr, 0, spStrokeStyle.put());
684
- }
685
- D2D1::Matrix3x2F originalTransform;
686
- D2D1::Matrix3x2F translationTransform =
687
- D2D1::Matrix3x2F::Translation(-textureRect.left + offset.x, -textureRect.top + offset.y);
688
-
689
- pRT->GetTransform(&originalTransform);
690
- translationTransform = originalTransform * translationTransform;
691
-
692
- pRT->SetTransform(translationTransform);
693
-
694
- DrawShape(pRT, shape, spBorderBrush.get(), strokeWidth, spStrokeStyle.get());
695
-
696
- pRT->SetTransform(originalTransform);
697
- }
698
- }
699
-
700
- template <typename TShape>
701
- void SetBorderLayerProperties(
702
- winrt::Microsoft::ReactNative::Composition::implementation::Theme *theme,
703
- winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
704
- winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual &layer,
705
- TShape &shape,
706
- winrt::com_ptr<::Microsoft::ReactNative::Composition::Experimental::ICompositionDrawingSurfaceInterop>
707
- &borderTexture,
708
- const D2D1_RECT_F &textureRect,
709
- facebook::react::Point anchorPoint,
710
- facebook::react::Point anchorOffset,
711
- winrt::Windows::Foundation::Numerics::float2 size,
712
- winrt::Windows::Foundation::Numerics::float2 relativeSizeAdjustment,
713
- FLOAT strokeWidth,
714
- const facebook::react::SharedColor &borderColor,
715
- facebook::react::BorderStyle borderStyle) {
716
- if constexpr (!std::is_base_of_v<ID2D1GeometryGroup, TShape>) {
717
- SetBorderLayerPropertiesCommon(
718
- theme,
719
- compContext,
720
- layer,
721
- shape,
722
- borderTexture,
723
- textureRect,
724
- anchorPoint,
725
- anchorOffset,
726
- size,
727
- relativeSizeAdjustment,
728
- strokeWidth,
729
- borderColor,
730
- borderStyle);
731
- } else {
732
- // if (VisualVersion::IsUseWinCompClippingRegionEnabled())
733
- {
734
- layer.Offset({anchorOffset.x, anchorOffset.y, 0}, {anchorPoint.x, anchorPoint.y, 0});
735
- layer.RelativeSizeWithOffset(
736
- {textureRect.right - textureRect.left, textureRect.bottom - textureRect.top}, {0.0f, 0.0f});
737
-
738
- layer.Brush(theme->Brush(*borderColor));
739
-
740
- winrt::com_ptr<ID2D1Factory1> spD2dFactory;
741
- compContext.as<::Microsoft::ReactNative::Composition::Experimental::ICompositionContextInterop>()->D2DFactory(
742
- spD2dFactory.put());
743
-
744
- winrt::com_ptr<ID2D1TransformedGeometry> transformedShape;
745
- D2D1::Matrix3x2F translationTransform = D2D1::Matrix3x2F::Translation(-textureRect.left, -textureRect.top);
746
- winrt::check_hresult(
747
- spD2dFactory->CreateTransformedGeometry(&shape, &translationTransform, transformedShape.put()));
748
-
749
- layer.as<::Microsoft::ReactNative::Composition::Experimental::IVisualInterop>()->SetClippingPath(
750
- transformedShape.get());
751
- }
752
- /*
753
- else
754
- {
755
- SetBorderLayerPropertiesCommon(theme, comContext, layer, shape, borderTexture, textureRect,
756
- anchorPoint, anchorOffset, strokeWidth, borderColor, borderStyle);
757
- }
758
- */
759
- }
760
- }
761
-
762
- namespace AnchorPosition {
763
- const float Left = 0.0;
764
- const float Center = 0.5;
765
- const float Right = 1.0;
766
- const float Top = 0.0;
767
- const float Bottom = 1.0;
768
- } // namespace AnchorPosition
769
-
770
- template <typename TShape>
771
- void DrawAllBorderLayers(
772
- winrt::Microsoft::ReactNative::Composition::implementation::Theme *theme,
773
- winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
774
- std::array<
775
- winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual,
776
- ComponentView::SpecialBorderLayerCount> &spBorderLayers,
777
- TShape &shape,
778
- const facebook::react::BorderWidths &borderWidths,
779
- const facebook::react::BorderRadii &borderRadii,
780
- float textureWidth,
781
- float textureHeight,
782
- const facebook::react::BorderColors &borderColors,
783
- facebook::react::BorderStyle borderStyle) {
784
- // Now that we've drawn our nice border in one layer, split it into its component layers
785
- winrt::com_ptr<::Microsoft::ReactNative::Composition::Experimental::ICompositionDrawingSurfaceInterop>
786
- spTextures[ComponentView::SpecialBorderLayerCount];
787
-
788
- // Set component border properties
789
- // Top Left Corner
790
- SetBorderLayerProperties(
791
- theme,
792
- compContext,
793
- spBorderLayers[0],
794
- shape,
795
- spTextures[0], // Target Layer, Source Texture, Target Texture
796
- {0,
797
- 0,
798
- borderRadii.topLeft.vertical + borderWidths.left,
799
- borderRadii.topLeft.horizontal + borderWidths.top}, // Texture Left, Top, Width, Height
800
- {AnchorPosition::Left, AnchorPosition::Top}, // Layer Anchor Point
801
- {0, 0}, // Layer Anchor Offset
802
- {borderRadii.topLeft.vertical + borderWidths.left, borderRadii.topLeft.horizontal + borderWidths.top}, // size
803
- {0.0f, 0.0f}, // relativeSize
804
- std::max(borderWidths.left, borderWidths.top),
805
- borderColors.left ? borderColors.left : borderColors.top,
806
- borderStyle);
807
-
808
- // Top Edge Border
809
- SetBorderLayerProperties(
810
- theme,
811
- compContext,
812
- spBorderLayers[1],
813
- shape,
814
- spTextures[1],
815
- {borderRadii.topLeft.vertical + borderWidths.left,
816
- 0,
817
- textureWidth - (borderRadii.topRight.vertical + borderWidths.right),
818
- borderWidths.top},
819
- {AnchorPosition::Left, AnchorPosition::Top},
820
- {borderRadii.topLeft.vertical + borderWidths.left, 0},
821
- {-(borderRadii.topLeft.vertical + borderWidths.left + borderRadii.topRight.vertical + borderWidths.right),
822
- borderWidths.top}, // size
823
- {1.0f, 0.0f}, // relativeSize
824
- borderWidths.top,
825
- borderColors.top,
826
- borderStyle);
827
-
828
- // Top Right Corner Border
829
- SetBorderLayerProperties(
830
- theme,
831
- compContext,
832
- spBorderLayers[2],
833
- shape,
834
- spTextures[2],
835
- {textureWidth - (borderRadii.topRight.vertical + borderWidths.right),
836
- 0,
837
- textureWidth,
838
- borderRadii.topRight.horizontal + borderWidths.top},
839
- {AnchorPosition::Right, AnchorPosition::Top},
840
- {-(borderRadii.topRight.vertical + borderWidths.right), 0},
841
- {borderRadii.topRight.vertical + borderWidths.right, borderRadii.topRight.horizontal + borderWidths.top},
842
- {0.0f, 0.0f},
843
- std::max(borderWidths.right, borderWidths.top),
844
- borderColors.right ? borderColors.right : borderColors.top,
845
- borderStyle);
846
-
847
- // Right Edge Border
848
- SetBorderLayerProperties(
849
- theme,
850
- compContext,
851
- spBorderLayers[3],
852
- shape,
853
- spTextures[3],
854
- {textureWidth - borderWidths.right,
855
- borderWidths.top + borderRadii.topRight.horizontal,
856
- textureWidth,
857
- textureHeight - (borderWidths.bottom + borderRadii.bottomRight.horizontal)},
858
- {AnchorPosition::Right, AnchorPosition::Top},
859
- {-borderWidths.right, borderWidths.top + borderRadii.topRight.horizontal},
860
- {borderWidths.right,
861
- -(borderWidths.top + borderRadii.topRight.horizontal + borderWidths.bottom +
862
- borderRadii.bottomRight.horizontal)}, // size
863
- {0.0f, 1.0f},
864
- borderWidths.right,
865
- borderColors.right,
866
- borderStyle);
867
-
868
- // Bottom Right Corner Border
869
- SetBorderLayerProperties(
870
- theme,
871
- compContext,
872
- spBorderLayers[4],
873
- shape,
874
- spTextures[4],
875
- {textureWidth - (borderWidths.right + borderRadii.bottomRight.vertical),
876
- textureHeight - (borderWidths.bottom + borderRadii.bottomRight.horizontal),
877
- textureWidth,
878
- textureHeight},
879
- {AnchorPosition::Right, AnchorPosition::Bottom},
880
- {-(borderWidths.right + borderRadii.bottomRight.vertical),
881
- -(borderWidths.bottom + borderRadii.bottomRight.horizontal)},
882
- {borderWidths.right + borderRadii.bottomRight.vertical, borderWidths.bottom + borderRadii.bottomRight.horizontal},
883
- {0, 0},
884
- std::max(borderWidths.right, borderWidths.bottom),
885
- borderColors.right ? borderColors.right : borderColors.bottom,
886
- borderStyle);
887
-
888
- // Bottom Edge Border
889
- SetBorderLayerProperties(
890
- theme,
891
- compContext,
892
- spBorderLayers[5],
893
- shape,
894
- spTextures[5],
895
- {borderWidths.left + borderRadii.bottomLeft.vertical,
896
- textureHeight - borderWidths.bottom,
897
- textureWidth - (borderWidths.right + borderRadii.bottomRight.vertical),
898
- textureHeight},
899
- {AnchorPosition::Left, AnchorPosition::Bottom},
900
- {borderWidths.left + borderRadii.bottomLeft.vertical, -borderWidths.bottom},
901
- {-(borderWidths.right + borderRadii.bottomLeft.vertical + borderWidths.left + borderRadii.bottomRight.vertical),
902
- borderWidths.bottom},
903
- {1.0f, 0.0f},
904
- borderWidths.bottom,
905
- borderColors.bottom,
906
- borderStyle);
907
-
908
- // Bottom Left Corner Border
909
- SetBorderLayerProperties(
910
- theme,
911
- compContext,
912
- spBorderLayers[6],
913
- shape,
914
- spTextures[6],
915
- {0,
916
- textureHeight - (borderWidths.bottom + borderRadii.bottomLeft.horizontal),
917
- borderWidths.left + borderRadii.bottomLeft.vertical,
918
- textureHeight},
919
- {AnchorPosition::Left, AnchorPosition::Bottom},
920
- {0, -(borderWidths.bottom + borderRadii.bottomLeft.horizontal)},
921
- {borderWidths.left + borderRadii.bottomLeft.vertical, borderWidths.bottom + borderRadii.bottomLeft.horizontal},
922
- {0, 0},
923
- std::max(borderWidths.left, borderWidths.bottom),
924
- borderColors.left ? borderColors.left : borderColors.bottom,
925
- borderStyle);
926
-
927
- // Left Edge Border
928
- SetBorderLayerProperties(
929
- theme,
930
- compContext,
931
- spBorderLayers[7],
932
- shape,
933
- spTextures[7],
934
- {0,
935
- borderWidths.top + borderRadii.topLeft.horizontal,
936
- borderWidths.left,
937
- textureHeight - (borderWidths.bottom + borderRadii.bottomLeft.horizontal)},
938
- {AnchorPosition::Left, AnchorPosition::Top},
939
- {0, borderWidths.top + borderRadii.topLeft.horizontal},
940
- {borderWidths.left,
941
- -(borderWidths.top + borderRadii.topLeft.horizontal + borderWidths.bottom + borderRadii.bottomLeft.horizontal)},
942
- {0, 1},
943
- borderWidths.left,
944
- borderColors.left,
945
- borderStyle);
946
- }
947
-
948
- winrt::com_ptr<ID2D1GeometryGroup> GetGeometryForRoundedBorder(
949
- winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
950
- const facebook::react::RectangleCorners<facebook::react::CornerRadii> &radius,
951
- const facebook::react::RectangleEdges<float> &inset,
952
- const facebook::react::RectangleEdges<float> &thickness,
953
- const facebook::react::RectangleEdges<float> &rectPathGeometry) noexcept {
954
- winrt::com_ptr<ID2D1PathGeometry> outerPathGeometry =
955
- GenerateRoundedRectPathGeometry(compContext, radius, inset, rectPathGeometry);
956
-
957
- if (outerPathGeometry == nullptr) {
958
- assert(false);
959
- return nullptr;
960
- }
961
-
962
- facebook::react::RectangleEdges<float> rectInnerPathGeometry = {
963
- rectPathGeometry.left + thickness.left,
964
- rectPathGeometry.top + thickness.top,
965
- rectPathGeometry.right - thickness.right,
966
- rectPathGeometry.bottom - thickness.bottom};
967
-
968
- // Total thickness is larger than original element size.
969
- // Clamp inner rect to have a width/height of 0, but placed such that the ratio of side-thicknesses is respected.
970
- // We need to respect this ratio so that any animations work properly.
971
-
972
- if (rectInnerPathGeometry.left > rectInnerPathGeometry.right) {
973
- float leftRatio = thickness.left / (thickness.left + thickness.right);
974
- auto x = std::floor(rectPathGeometry.left + ((rectPathGeometry.right - rectPathGeometry.left) * leftRatio));
975
- rectInnerPathGeometry.left = x;
976
- rectInnerPathGeometry.right = x;
977
- }
978
-
979
- if (rectInnerPathGeometry.top > rectInnerPathGeometry.bottom) {
980
- float topRatio = thickness.top / (thickness.top + thickness.bottom);
981
- auto y = rectPathGeometry.top + std::floor((rectPathGeometry.top - rectPathGeometry.bottom) * topRatio);
982
- rectInnerPathGeometry.top = y;
983
- rectInnerPathGeometry.bottom = y;
984
- }
985
-
986
- facebook::react::RectangleEdges<float> innerInset = {
987
- inset.left + thickness.left,
988
- inset.top + thickness.top,
989
- inset.right + thickness.right,
990
- inset.bottom + thickness.bottom};
991
-
992
- winrt::com_ptr<ID2D1PathGeometry> innerPathGeometry =
993
- GenerateRoundedRectPathGeometry(compContext, radius, innerInset, rectInnerPathGeometry);
994
-
995
- if (innerPathGeometry == nullptr) {
996
- assert(false); // Failed to create inner pathGeometry for rounded border
997
- return nullptr;
998
- }
999
-
1000
- ID2D1Geometry *ppGeometries[] = {outerPathGeometry.get(), innerPathGeometry.get()};
1001
- winrt::com_ptr<ID2D1Factory1> spD2dFactory;
1002
- compContext.as<::Microsoft::ReactNative::Composition::Experimental::ICompositionContextInterop>()->D2DFactory(
1003
- spD2dFactory.put());
1004
-
1005
- winrt::com_ptr<ID2D1GeometryGroup> geometryGroup = nullptr;
1006
- // Create a geometry group.
1007
- HRESULT hr = spD2dFactory->CreateGeometryGroup(
1008
- D2D1_FILL_MODE_ALTERNATE, ppGeometries, ARRAYSIZE(ppGeometries), geometryGroup.put());
1009
-
1010
- if (SUCCEEDED(hr)) {
1011
- return geometryGroup;
1012
- }
1013
- return nullptr;
1014
- }
1015
-
1016
- // We don't want half pixel borders, or border radii - they lead to blurry borders
1017
- // Also apply scale factor to the radii at this point
1018
- void pixelRoundBorderRadii(facebook::react::BorderRadii &borderRadii, float scaleFactor) noexcept {
1019
- // Always round radii down to avoid spikey circles
1020
- borderRadii.topLeft = {
1021
- std::floor(borderRadii.topLeft.horizontal * scaleFactor), std::floor(borderRadii.topLeft.vertical * scaleFactor)};
1022
- borderRadii.topRight = {
1023
- std::floor(borderRadii.topRight.horizontal * scaleFactor),
1024
- std::floor(borderRadii.topRight.vertical * scaleFactor)};
1025
- borderRadii.bottomLeft = {
1026
- std::floor(borderRadii.bottomLeft.horizontal * scaleFactor),
1027
- std::floor(borderRadii.bottomLeft.vertical * scaleFactor)};
1028
- borderRadii.bottomRight = {
1029
- std::floor(borderRadii.bottomRight.horizontal * scaleFactor),
1030
- std::floor(borderRadii.bottomRight.vertical * scaleFactor)};
1031
- }
1032
-
1033
- void scaleAndPixelRoundBorderWidths(
1034
- facebook::react::LayoutMetrics const &layoutMetrics,
1035
- facebook::react::BorderMetrics &borderMetrics,
1036
- float scaleFactor) noexcept {
1037
- borderMetrics.borderWidths.left = (borderMetrics.borderWidths.left == 0)
1038
- ? 0.f
1039
- : std::max(1.f, std::round(borderMetrics.borderWidths.left * scaleFactor));
1040
- borderMetrics.borderWidths.top = (borderMetrics.borderWidths.top == 0)
1041
- ? 0.f
1042
- : std::max(1.f, std::round(borderMetrics.borderWidths.top * scaleFactor));
1043
- borderMetrics.borderWidths.right = (borderMetrics.borderWidths.right == 0)
1044
- ? 0.f
1045
- : std::max(1.f, std::round(borderMetrics.borderWidths.right * scaleFactor));
1046
- borderMetrics.borderWidths.bottom = (borderMetrics.borderWidths.bottom == 0)
1047
- ? 0.f
1048
- : std::max(1.f, std::round(borderMetrics.borderWidths.bottom * scaleFactor));
1049
-
1050
- // If we rounded both sides of the borderWidths up, we may have made the borderWidths larger than the total
1051
- if (layoutMetrics.frame.size.width * scaleFactor <
1052
- (borderMetrics.borderWidths.left + borderMetrics.borderWidths.right)) {
1053
- borderMetrics.borderWidths.right--;
1054
- }
1055
- if (layoutMetrics.frame.size.height * scaleFactor <
1056
- (borderMetrics.borderWidths.top + borderMetrics.borderWidths.bottom)) {
1057
- borderMetrics.borderWidths.bottom--;
1058
- }
1059
- }
1060
-
1061
- // react-native uses black as a default color when none is specified.
1062
- void assignDefaultBlackBorders(facebook::react::BorderMetrics &borderMetrics) noexcept {
1063
- if (!borderMetrics.borderColors.left) {
1064
- borderMetrics.borderColors.left = facebook::react::blackColor();
1065
- }
1066
- if (!borderMetrics.borderColors.top) {
1067
- borderMetrics.borderColors.top = facebook::react::blackColor();
1068
- }
1069
- if (!borderMetrics.borderColors.right) {
1070
- borderMetrics.borderColors.right = facebook::react::blackColor();
1071
- }
1072
- if (!borderMetrics.borderColors.bottom) {
1073
- borderMetrics.borderColors.bottom = facebook::react::blackColor();
1074
- }
1075
- }
1076
-
1077
- facebook::react::BorderMetrics resolveAndAlignBorderMetrics(
1078
- facebook::react::LayoutMetrics const &layoutMetrics,
1079
- const facebook::react::ViewProps &viewProps) noexcept {
1080
- auto borderMetrics = viewProps.resolveBorderMetrics(layoutMetrics);
1081
-
1082
- pixelRoundBorderRadii(borderMetrics.borderRadii, layoutMetrics.pointScaleFactor);
1083
- scaleAndPixelRoundBorderWidths(layoutMetrics, borderMetrics, layoutMetrics.pointScaleFactor);
1084
- assignDefaultBlackBorders(borderMetrics);
1085
- return borderMetrics;
534
+ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ComponentView::OuterVisual() const noexcept {
535
+ return m_outerVisual ? m_outerVisual : Visual();
1086
536
  }
1087
537
 
1088
- bool ComponentView::TryUpdateSpecialBorderLayers(
1089
- winrt::Microsoft::ReactNative::Composition::implementation::Theme *theme,
1090
- std::array<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual, SpecialBorderLayerCount>
1091
- &spBorderVisuals,
1092
- facebook::react::LayoutMetrics const &layoutMetrics,
1093
- const facebook::react::ViewProps &viewProps) noexcept {
1094
- auto borderMetrics = resolveAndAlignBorderMetrics(layoutMetrics, viewProps);
1095
- // We only handle a single borderStyle for now
1096
- auto borderStyle = borderMetrics.borderStyles.left;
1097
-
1098
- bool hasMeaningfulColor =
1099
- !borderMetrics.borderColors.isUniform() || !facebook::react::isColorMeaningful(borderMetrics.borderColors.left);
1100
- bool hasMeaningfulWidth = !borderMetrics.borderWidths.isUniform() || (borderMetrics.borderWidths.left != 0);
1101
- if (!hasMeaningfulColor && !hasMeaningfulWidth) {
1102
- return false;
1103
- }
1104
-
1105
- // Create the special border layers if they don't exist yet
1106
- if (!spBorderVisuals[0]) {
1107
- for (uint8_t i = 0; i < SpecialBorderLayerCount; i++) {
1108
- auto visual = m_compContext.CreateSpriteVisual();
1109
- Visual().InsertAt(visual, i);
1110
- spBorderVisuals[i] = std::move(visual);
1111
- m_numBorderVisuals++;
1112
- }
1113
- }
1114
-
1115
- float extentWidth = layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor;
1116
- float extentHeight = layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor;
1117
-
1118
- if (borderMetrics.borderRadii.topLeft.horizontal != 0 || borderMetrics.borderRadii.topRight.horizontal != 0 ||
1119
- borderMetrics.borderRadii.bottomLeft.horizontal != 0 || borderMetrics.borderRadii.bottomRight.horizontal != 0 ||
1120
- borderMetrics.borderRadii.topLeft.vertical != 0 || borderMetrics.borderRadii.topRight.vertical != 0 ||
1121
- borderMetrics.borderRadii.bottomLeft.vertical != 0 || borderMetrics.borderRadii.bottomRight.vertical != 0) {
1122
- if (borderStyle == facebook::react::BorderStyle::Dotted || borderStyle == facebook::react::BorderStyle::Dashed) {
1123
- // Because in DirectX geometry starts at the center of the stroke, we need to deflate
1124
- // rectangle by half the stroke width to render correctly.
1125
- facebook::react::RectangleEdges<float> rectPathGeometry = {
1126
- borderMetrics.borderWidths.left / 2.0f,
1127
- borderMetrics.borderWidths.top / 2.0f,
1128
- extentWidth - borderMetrics.borderWidths.right / 2.0f,
1129
- extentHeight - borderMetrics.borderWidths.bottom / 2.0f};
1130
-
1131
- winrt::com_ptr<ID2D1PathGeometry> pathGeometry =
1132
- GenerateRoundedRectPathGeometry(m_compContext, borderMetrics.borderRadii, {0, 0, 0, 0}, rectPathGeometry);
1133
-
1134
- if (pathGeometry) {
1135
- DrawAllBorderLayers(
1136
- theme,
1137
- m_compContext,
1138
- spBorderVisuals,
1139
- *pathGeometry,
1140
- borderMetrics.borderWidths,
1141
- borderMetrics.borderRadii,
1142
- extentWidth,
1143
- extentHeight,
1144
- borderMetrics.borderColors,
1145
- borderStyle);
1146
- } else {
1147
- assert(false);
538
+ facebook::react::LayoutMetrics ComponentView::focusLayoutMetrics(bool inner) const noexcept {
539
+ facebook::react::LayoutMetrics layoutMetrics = m_layoutMetrics;
540
+ layoutMetrics.frame.origin.x -= FOCUS_VISUAL_WIDTH * (inner ? 1 : 2);
541
+ layoutMetrics.frame.origin.y -= FOCUS_VISUAL_WIDTH * (inner ? 1 : 2);
542
+ layoutMetrics.frame.size.height += FOCUS_VISUAL_WIDTH * (inner ? 2 : 4);
543
+ layoutMetrics.frame.size.width += FOCUS_VISUAL_WIDTH * (inner ? 2 : 4);
544
+ return layoutMetrics;
545
+ }
546
+
547
+ facebook::react::BorderMetrics ComponentView::focusBorderMetrics(
548
+ bool inner,
549
+ const facebook::react::LayoutMetrics &layoutMetrics) const noexcept {
550
+ facebook::react::BorderMetrics metrics = BorderPrimitive::resolveAndAlignBorderMetrics(layoutMetrics, *viewProps());
551
+ facebook::react::Color innerColor;
552
+ innerColor.m_color = {1, 0, 0, 0};
553
+ innerColor.m_platformColor.push_back(inner ? "FocusVisualSecondary" : "FocusVisualPrimary");
554
+ metrics.borderColors.bottom = metrics.borderColors.left = metrics.borderColors.right = metrics.borderColors.top =
555
+ innerColor;
556
+ if (metrics.borderRadii.bottomLeft.horizontal != 0)
557
+ metrics.borderRadii.bottomLeft.horizontal += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2);
558
+ if (metrics.borderRadii.bottomLeft.vertical != 0)
559
+ metrics.borderRadii.bottomLeft.vertical += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2);
560
+ if (metrics.borderRadii.bottomRight.horizontal != 0)
561
+ metrics.borderRadii.bottomRight.horizontal += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2);
562
+ if (metrics.borderRadii.bottomRight.vertical != 0)
563
+ metrics.borderRadii.bottomRight.vertical += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2);
564
+ if (metrics.borderRadii.topLeft.horizontal != 0)
565
+ metrics.borderRadii.topLeft.horizontal += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2);
566
+ if (metrics.borderRadii.topLeft.vertical != 0)
567
+ metrics.borderRadii.topLeft.vertical += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2);
568
+ if (metrics.borderRadii.topRight.horizontal != 0)
569
+ metrics.borderRadii.topRight.horizontal += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2);
570
+ if (metrics.borderRadii.topRight.vertical != 0)
571
+ metrics.borderRadii.topRight.vertical += FOCUS_VISUAL_WIDTH * (inner ? 1 : 2);
572
+
573
+ metrics.borderStyles.bottom = metrics.borderStyles.left = metrics.borderStyles.right = metrics.borderStyles.top =
574
+ facebook::react::BorderStyle::Solid;
575
+ metrics.borderWidths.bottom = metrics.borderWidths.left = metrics.borderWidths.right = metrics.borderWidths.top =
576
+ FOCUS_VISUAL_WIDTH * layoutMetrics.pointScaleFactor;
577
+ return metrics;
578
+ }
579
+
580
+ void ComponentView::hostFocusVisual(bool show, winrt::com_ptr<ComponentView> view) noexcept {
581
+ if ((view->m_flags & ComponentViewFeatures::FocusVisual) == ComponentViewFeatures::FocusVisual) {
582
+ // Any previous view showing focus visuals should have removed them before another shows it
583
+ assert(
584
+ !m_focusPrimitive || !m_focusPrimitive->m_focusVisualComponent ||
585
+ m_focusPrimitive->m_focusVisualComponent == view);
586
+ assert(
587
+ !m_focusPrimitive || !m_focusPrimitive->m_focusVisualComponent ||
588
+ view->m_componentHostingFocusVisual.get() == this);
589
+ if (show && !view->m_componentHostingFocusVisual) {
590
+ view->m_componentHostingFocusVisual = get_strong();
591
+
592
+ if (!m_focusPrimitive) {
593
+ m_focusPrimitive = std::make_unique<FocusPrimitive>();
594
+ }
595
+ m_focusPrimitive->m_focusVisualComponent = view;
596
+
597
+ if (!m_focusPrimitive->m_focusVisual) {
598
+ m_focusPrimitive->m_focusVisual = m_compContext.CreateSpriteVisual();
599
+ auto hostingVisual =
600
+ winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
601
+ visualToHostFocus())
602
+ .as<winrt::Microsoft::UI::Composition::ContainerVisual>();
603
+ if (hostingVisual) {
604
+ hostingVisual.Children().InsertAtTop(
605
+ winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
606
+ m_focusPrimitive->m_focusVisual));
607
+ } else {
608
+ assert(
609
+ view.get() ==
610
+ this); // When not using lifted comp, focus visuals should always host within their own component
611
+ OuterVisual().InsertAt(m_focusPrimitive->m_focusVisual, 1);
612
+ }
1148
613
  }
1149
- } else {
1150
- facebook::react::RectangleEdges<float> rectPathGeometry = {0, 0, extentWidth, extentHeight};
1151
-
1152
- winrt::com_ptr<ID2D1GeometryGroup> pathGeometry = GetGeometryForRoundedBorder(
1153
- m_compContext,
1154
- borderMetrics.borderRadii,
1155
- {0, 0, 0, 0}, // inset
1156
- borderMetrics.borderWidths,
1157
- rectPathGeometry);
1158
-
1159
- DrawAllBorderLayers(
1160
- theme,
1161
- m_compContext,
1162
- spBorderVisuals,
1163
- *pathGeometry,
1164
- borderMetrics.borderWidths,
1165
- borderMetrics.borderRadii,
1166
- extentWidth,
1167
- extentHeight,
1168
- borderMetrics.borderColors,
1169
- borderStyle);
1170
- }
1171
- } else {
1172
- // Because in DirectX geometry starts at the center of the stroke, we need to deflate rectangle by half the stroke
1173
- // width / height to render correctly.
1174
- D2D1_RECT_F rectShape{
1175
- borderMetrics.borderWidths.left / 2.0f,
1176
- borderMetrics.borderWidths.top / 2.0f,
1177
- extentWidth - (borderMetrics.borderWidths.right / 2.0f),
1178
- extentHeight - (borderMetrics.borderWidths.bottom / 2.0f)};
1179
- DrawAllBorderLayers(
1180
- theme,
1181
- m_compContext,
1182
- spBorderVisuals,
1183
- rectShape,
1184
- borderMetrics.borderWidths,
1185
- borderMetrics.borderRadii,
1186
- extentWidth,
1187
- extentHeight,
1188
- borderMetrics.borderColors,
1189
- borderStyle);
1190
- }
1191
- return true;
1192
- }
1193
-
1194
- void ComponentView::finalizeBorderUpdates(
1195
- facebook::react::LayoutMetrics const &layoutMetrics,
1196
- const facebook::react::ViewProps &viewProps) noexcept {
1197
- if (!m_needsBorderUpdate || theme()->IsEmpty()) {
1198
- return;
1199
- }
1200
-
1201
- m_needsBorderUpdate = false;
1202
- auto spBorderLayers = FindSpecialBorderLayers();
1203
614
 
1204
- if (!TryUpdateSpecialBorderLayers(theme(), spBorderLayers, layoutMetrics, viewProps)) {
1205
- for (auto &spBorderLayer : spBorderLayers) {
1206
- if (spBorderLayer) {
1207
- spBorderLayer.as<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual>().Brush(nullptr);
615
+ m_focusPrimitive->m_focusVisual.IsVisible(true);
616
+ assert(view->viewProps()->enableFocusRing);
617
+ if (!m_focusPrimitive->m_focusInnerPrimitive) {
618
+ m_focusPrimitive->m_focusInnerPrimitive = std::make_shared<BorderPrimitive>(*this);
619
+ m_focusPrimitive->m_focusVisual.InsertAt(m_focusPrimitive->m_focusInnerPrimitive->RootVisual(), 0);
620
+ }
621
+ if (!m_focusPrimitive->m_focusOuterPrimitive) {
622
+ m_focusPrimitive->m_focusOuterPrimitive = std::make_shared<BorderPrimitive>(*this);
623
+ m_focusPrimitive->m_focusVisual.InsertAt(m_focusPrimitive->m_focusOuterPrimitive->RootVisual(), 0);
624
+ }
625
+ if (auto focusVisual =
626
+ winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
627
+ m_focusPrimitive->m_focusVisual)) {
628
+ auto outerVisual =
629
+ winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
630
+ view->OuterVisual());
631
+ focusVisual.ParentForTransform(outerVisual);
1208
632
  }
633
+ updateFocusLayoutMetrics();
634
+ auto innerFocusMetrics = view->focusLayoutMetrics(true /*inner*/);
635
+ m_focusPrimitive->m_focusInnerPrimitive->finalize(
636
+ innerFocusMetrics, view->focusBorderMetrics(true /*inner*/, innerFocusMetrics));
637
+ auto outerFocusMetrics = view->focusLayoutMetrics(false /*inner*/);
638
+ m_focusPrimitive->m_focusOuterPrimitive->finalize(
639
+ outerFocusMetrics, view->focusBorderMetrics(false /*inner*/, outerFocusMetrics));
640
+ } else if (!show && view->m_componentHostingFocusVisual && m_focusPrimitive) {
641
+ m_focusPrimitive->m_focusVisualComponent = nullptr;
642
+ m_focusPrimitive->m_focusVisual.IsVisible(false);
643
+ view->m_componentHostingFocusVisual = nullptr;
1209
644
  }
1210
645
  }
1211
646
  }
1212
647
 
1213
- winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ComponentView::OuterVisual() const noexcept {
1214
- return m_outerVisual ? m_outerVisual : Visual();
1215
- }
1216
-
1217
- void ComponentView::showFocusVisual(bool show) noexcept {
1218
- if (show) {
1219
- assert(m_enableFocusVisual);
1220
- m_focusVisual.IsFocused(true);
1221
- } else {
1222
- m_focusVisual.IsFocused(false);
1223
- }
1224
- }
1225
-
1226
- void ComponentView::updateBorderProps(
1227
- const facebook::react::ViewProps &oldViewProps,
1228
- const facebook::react::ViewProps &newViewProps) noexcept {
1229
- if (oldViewProps.borderColors != newViewProps.borderColors || oldViewProps.borderRadii != newViewProps.borderRadii ||
1230
- !(oldViewProps.yogaStyle.border(facebook::yoga::Edge::All) ==
1231
- newViewProps.yogaStyle.border(facebook::yoga::Edge::All)) ||
1232
- oldViewProps.borderStyles != newViewProps.borderStyles) {
1233
- m_needsBorderUpdate = true;
1234
- }
1235
-
1236
- m_enableFocusVisual = newViewProps.enableFocusRing;
1237
- if (!m_enableFocusVisual) {
1238
- showFocusVisual(false);
1239
- }
1240
- }
1241
-
1242
648
  void ComponentView::updateShadowProps(
1243
649
  const facebook::react::ViewProps &oldViewProps,
1244
650
  const facebook::react::ViewProps &newViewProps) noexcept {
1245
651
  // Shadow Properties
1246
652
  if (oldViewProps.shadowOffset != newViewProps.shadowOffset || oldViewProps.shadowColor != newViewProps.shadowColor ||
1247
653
  oldViewProps.shadowOpacity != newViewProps.shadowOpacity ||
1248
- oldViewProps.shadowRadius != newViewProps.shadowRadius) {
654
+ oldViewProps.shadowRadius != newViewProps.shadowRadius || oldViewProps.boxShadow != newViewProps.boxShadow) {
1249
655
  applyShadowProps(newViewProps);
1250
656
  }
1251
657
  }
1252
658
 
1253
659
  void ComponentView::applyShadowProps(const facebook::react::ViewProps &viewProps) noexcept {
1254
660
  auto shadow = m_compContext.CreateDropShadow();
1255
- shadow.Offset({viewProps.shadowOffset.width, viewProps.shadowOffset.height, 0});
1256
- shadow.Opacity(viewProps.shadowOpacity);
1257
- shadow.BlurRadius(viewProps.shadowRadius);
1258
- if (viewProps.shadowColor)
1259
- shadow.Color(theme()->Color(*viewProps.shadowColor));
661
+ if (!viewProps.boxShadow.empty()) {
662
+ shadow.Offset({viewProps.boxShadow[0].offsetX, viewProps.boxShadow[0].offsetY, 0});
663
+ shadow.Opacity(1);
664
+ shadow.BlurRadius(viewProps.boxShadow[0].blurRadius);
665
+ shadow.Color(theme()->Color(*viewProps.boxShadow[0].color));
666
+ } else {
667
+ shadow.Offset({viewProps.shadowOffset.width, viewProps.shadowOffset.height, 0});
668
+ shadow.Opacity(viewProps.shadowOpacity);
669
+ shadow.BlurRadius(viewProps.shadowRadius);
670
+ if (viewProps.shadowColor)
671
+ shadow.Color(theme()->Color(*viewProps.shadowColor));
672
+ }
673
+
1260
674
  Visual().as<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual>().Shadow(shadow);
1261
675
  }
1262
676
 
@@ -1347,6 +761,19 @@ void ComponentView::updateAccessibilityProps(
1347
761
  UIA_LiveSettingPropertyId,
1348
762
  oldViewProps.accessibilityLiveRegion,
1349
763
  newViewProps.accessibilityLiveRegion);
764
+
765
+ if ((oldViewProps.accessibilityState.has_value() && oldViewProps.accessibilityState->selected.has_value()) !=
766
+ ((newViewProps.accessibilityState.has_value() && newViewProps.accessibilityState->selected.has_value()))) {
767
+ auto compProvider =
768
+ m_uiaProvider.try_as<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>();
769
+ if (compProvider) {
770
+ if ((newViewProps.accessibilityState.has_value() && newViewProps.accessibilityState->selected.has_value())) {
771
+ winrt::Microsoft::ReactNative::implementation::AddSelectionItemsToContainer(compProvider.get());
772
+ } else {
773
+ winrt::Microsoft::ReactNative::implementation::RemoveSelectionItemsFromContainer(compProvider.get());
774
+ }
775
+ }
776
+ }
1350
777
  }
1351
778
 
1352
779
  std::optional<std::string> ComponentView::getAccessiblityValue() noexcept {
@@ -1370,10 +797,10 @@ void ComponentView::Toggle() noexcept {
1370
797
  // no-op
1371
798
  }
1372
799
 
1373
- void ComponentView::updateBorderLayoutMetrics(
800
+ void ComponentView::updateClippingPath(
1374
801
  facebook::react::LayoutMetrics const &layoutMetrics,
1375
802
  const facebook::react::ViewProps &viewProps) noexcept {
1376
- auto borderMetrics = resolveAndAlignBorderMetrics(layoutMetrics, viewProps);
803
+ auto borderMetrics = BorderPrimitive::resolveAndAlignBorderMetrics(layoutMetrics, viewProps);
1377
804
 
1378
805
  if (borderMetrics.borderRadii.topLeft.horizontal == 0 && borderMetrics.borderRadii.topRight.horizontal == 0 &&
1379
806
  borderMetrics.borderRadii.bottomLeft.horizontal == 0 && borderMetrics.borderRadii.bottomRight.horizontal == 0 &&
@@ -1381,7 +808,7 @@ void ComponentView::updateBorderLayoutMetrics(
1381
808
  borderMetrics.borderRadii.bottomLeft.vertical == 0 && borderMetrics.borderRadii.bottomRight.vertical == 0) {
1382
809
  Visual().as<::Microsoft::ReactNative::Composition::Experimental::IVisualInterop>()->SetClippingPath(nullptr);
1383
810
  } else {
1384
- winrt::com_ptr<ID2D1PathGeometry> pathGeometry = GenerateRoundedRectPathGeometry(
811
+ winrt::com_ptr<ID2D1PathGeometry> pathGeometry = BorderPrimitive::GenerateRoundedRectPathGeometry(
1385
812
  m_compContext,
1386
813
  borderMetrics.borderRadii,
1387
814
  {0, 0, 0, 0},
@@ -1393,24 +820,16 @@ void ComponentView::updateBorderLayoutMetrics(
1393
820
  Visual().as<::Microsoft::ReactNative::Composition::Experimental::IVisualInterop>()->SetClippingPath(
1394
821
  pathGeometry.get());
1395
822
  }
823
+ }
1396
824
 
1397
- if (m_layoutMetrics != layoutMetrics) {
1398
- m_needsBorderUpdate = true;
1399
- }
1400
-
1401
- m_focusVisual.ScaleFactor(layoutMetrics.pointScaleFactor);
1402
- OuterVisual().Size(
1403
- {layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor,
1404
- layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor});
1405
- OuterVisual().Offset({
1406
- layoutMetrics.frame.origin.x * layoutMetrics.pointScaleFactor,
1407
- layoutMetrics.frame.origin.y * layoutMetrics.pointScaleFactor,
1408
- 0.0f,
1409
- });
825
+ std::pair<facebook::react::Cursor, HCURSOR> ComponentView::cursor() const noexcept {
826
+ return {viewProps()->cursor, nullptr};
1410
827
  }
1411
828
 
1412
829
  void ComponentView::indexOffsetForBorder(uint32_t &index) const noexcept {
1413
- index += m_numBorderVisuals;
830
+ if (m_borderPrimitive) {
831
+ index += m_borderPrimitive->numberOfVisuals();
832
+ }
1414
833
  }
1415
834
 
1416
835
  void ComponentView::OnRenderingDeviceLost() noexcept {}
@@ -1528,24 +947,15 @@ ViewComponentView::ViewComponentView(
1528
947
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
1529
948
  facebook::react::Tag tag,
1530
949
  winrt::Microsoft::ReactNative::ReactContext const &reactContext,
1531
- ComponentViewFeatures flags)
1532
- : base_type(compContext, tag, reactContext, flags),
950
+ ComponentViewFeatures flags,
951
+ winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder)
952
+ : base_type(compContext, tag, reactContext, flags, builder),
1533
953
  m_props(defaultProps ? defaultProps : ViewComponentView::defaultProps()) {}
1534
954
 
1535
955
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ViewComponentView::createVisual() noexcept {
1536
956
  return m_compContext.CreateSpriteVisual();
1537
957
  }
1538
958
 
1539
- void ViewComponentView::CreateVisualHandler(
1540
- const winrt::Microsoft::ReactNative::Composition::CreateVisualDelegate &handler) {
1541
- m_createVisualHandler = handler;
1542
- }
1543
-
1544
- winrt::Microsoft::ReactNative::Composition::CreateVisualDelegate ViewComponentView::CreateVisualHandler()
1545
- const noexcept {
1546
- return m_createVisualHandler;
1547
- }
1548
-
1549
959
  void ViewComponentView::CreateInternalVisualHandler(
1550
960
  const winrt::Microsoft::ReactNative::Composition::Experimental::CreateInternalVisualDelegate &handler) {
1551
961
  m_createInternalVisualHandler = handler;
@@ -1560,10 +970,10 @@ void ViewComponentView::ensureVisual() noexcept {
1560
970
  if (!m_visual) {
1561
971
  if (m_createInternalVisualHandler) {
1562
972
  m_visual = m_createInternalVisualHandler(*this);
1563
- } else if (m_createVisualHandler) {
973
+ } else if (m_builder && m_builder->CreateVisualHandler()) {
1564
974
  m_visual =
1565
975
  winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::CreateVisual(
1566
- m_createVisualHandler(*this));
976
+ m_builder->CreateVisualHandler()(*this));
1567
977
  } else {
1568
978
  m_visual = createVisual();
1569
979
  }
@@ -1579,6 +989,13 @@ winrt::Microsoft::ReactNative::ComponentView ViewComponentView::Create(
1579
989
  ViewComponentView::defaultProps(), compContext, tag, reactContext, ComponentViewFeatures::Default);
1580
990
  }
1581
991
 
992
+ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual
993
+ ViewComponentView::VisualToMountChildrenInto() noexcept {
994
+ if (m_builder && m_builder->VisualToMountChildrenIntoHandler())
995
+ return m_builder->VisualToMountChildrenIntoHandler()(*this);
996
+ return Visual();
997
+ }
998
+
1582
999
  void ViewComponentView::MountChildComponentView(
1583
1000
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
1584
1001
  uint32_t index) noexcept {
@@ -1598,7 +1015,7 @@ void ViewComponentView::MountChildComponentView(
1598
1015
  }
1599
1016
  }
1600
1017
  }
1601
- Visual().InsertAt(compositionChild->OuterVisual(), visualIndex);
1018
+ VisualToMountChildrenInto().InsertAt(compositionChild->OuterVisual(), visualIndex);
1602
1019
  } else {
1603
1020
  m_hasNonVisualChildren = true;
1604
1021
  }
@@ -1611,7 +1028,7 @@ void ViewComponentView::UnmountChildComponentView(
1611
1028
 
1612
1029
  indexOffsetForBorder(index);
1613
1030
  if (auto compositionChild = childComponentView.try_as<ComponentView>()) {
1614
- Visual().Remove(compositionChild->OuterVisual());
1031
+ VisualToMountChildrenInto().Remove(compositionChild->OuterVisual());
1615
1032
  }
1616
1033
  }
1617
1034
 
@@ -1823,7 +1240,7 @@ winrt::Microsoft::ReactNative::ViewProps ViewComponentView::ViewProps() noexcept
1823
1240
 
1824
1241
  winrt::Microsoft::ReactNative::ViewProps ViewComponentView::ViewPropsInner() noexcept {
1825
1242
  // If we have AbiViewProps, then we dont need to new up a props wrapper
1826
- if (m_customComponent) {
1243
+ if (m_builder) {
1827
1244
  const auto &abiViewProps = *std::static_pointer_cast<const ::Microsoft::ReactNative::AbiViewProps>(m_props);
1828
1245
  return abiViewProps.ViewProps();
1829
1246
  }
@@ -1913,6 +1330,9 @@ winrt::Microsoft::ReactNative::ComponentView lastDeepChild(
1913
1330
  return current;
1914
1331
  }
1915
1332
 
1333
+ // Walks the tree calling the function fn on each node.
1334
+ // If fn returns true, then walkTree stops itterating over the tree, and returns true.
1335
+ // If the tree walk completes without fn returning true, then walkTree returns false.
1916
1336
  bool walkTree(
1917
1337
  const winrt::Microsoft::ReactNative::ComponentView &view,
1918
1338
  bool forward,