react-native-windows 0.78.5 → 0.78.7

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 (189) hide show
  1. package/Directory.Build.props +6 -4
  2. package/Folly/Folly.vcxproj +46 -6
  3. package/Folly/Folly.vcxproj.filters +16 -4
  4. package/Folly/TEMP_UntilFollyUpdate/ConstexprMath.h +26 -18
  5. package/Folly/TEMP_UntilFollyUpdate/Conv.cpp +1205 -0
  6. package/Folly/TEMP_UntilFollyUpdate/chrono/Hardware.h +155 -0
  7. package/Folly/TEMP_UntilFollyUpdate/concurrency/CacheLocality.cpp +633 -0
  8. package/Folly/TEMP_UntilFollyUpdate/{dynamic-inl.h → json/dynamic-inl.h} +3 -4
  9. package/Folly/TEMP_UntilFollyUpdate/{json.cpp → json/json.cpp} +14 -10
  10. package/Folly/TEMP_UntilFollyUpdate/lang/SafeAssert.h +7 -14
  11. package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.h +6 -6
  12. package/Folly/ThreadNameStub.cpp +10 -0
  13. package/Folly/cgmanifest.json +11 -1
  14. package/Libraries/Components/View/View.windows.js +107 -56
  15. package/Libraries/Components/View/ViewAccessibility.d.ts +60 -1
  16. package/Libraries/Image/Image.windows.js +42 -21
  17. package/Libraries/Modal/Modal.d.ts +7 -0
  18. package/Libraries/Modal/Modal.windows.js +7 -1
  19. package/Libraries/NativeComponent/BaseViewConfig.windows.js +3 -0
  20. package/Libraries/Text/Text.d.ts +18 -0
  21. package/Microsoft.ReactNative/AsynchronousEventBeat.cpp +4 -25
  22. package/Microsoft.ReactNative/AsynchronousEventBeat.h +0 -3
  23. package/Microsoft.ReactNative/Base/FollyIncludes.h +1 -0
  24. package/Microsoft.ReactNative/CallInvoker.cpp +42 -0
  25. package/Microsoft.ReactNative/CallInvoker.h +34 -0
  26. package/Microsoft.ReactNative/{JSDispatcherWriter.cpp → CallInvokerWriter.cpp} +35 -47
  27. package/Microsoft.ReactNative/CallInvokerWriter.h +74 -0
  28. package/Microsoft.ReactNative/CompositionComponentView.idl +0 -5
  29. package/Microsoft.ReactNative/CompositionSwitcher.idl +7 -0
  30. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +8 -10
  31. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +4 -1
  32. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.cpp +12 -2
  33. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.h +2 -0
  34. package/Microsoft.ReactNative/Fabric/Composition/CompositionAnnotationProvider.cpp +100 -0
  35. package/Microsoft.ReactNative/Fabric/Composition/CompositionAnnotationProvider.h +31 -0
  36. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +77 -11
  37. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +43 -1
  38. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +7 -0
  39. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +86 -56
  40. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +5 -1
  41. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +0 -4
  42. package/Microsoft.ReactNative/Fabric/Composition/CompositionUIService.cpp +0 -2
  43. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +118 -63
  44. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +2 -0
  45. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +133 -8
  46. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +16 -2
  47. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +4 -2
  48. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +9 -1
  49. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.cpp +34 -11
  50. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.h +3 -0
  51. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +133 -135
  52. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +9 -6
  53. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +46 -49
  54. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +6 -1
  55. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +13 -8
  56. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +5 -2
  57. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +146 -25
  58. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +14 -0
  59. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +160 -12
  60. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +6 -0
  61. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputEventEmitter.cpp +47 -0
  62. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputEventEmitter.h +15 -1
  63. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.cpp +6 -2
  64. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h +4 -1
  65. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +7 -9
  66. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.h +4 -1
  67. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +5 -0
  68. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +40 -36
  69. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +68 -0
  70. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +11 -0
  71. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +70 -13
  72. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +10 -2
  73. package/Microsoft.ReactNative/Fabric/ImageManager.cpp +5 -5
  74. package/Microsoft.ReactNative/Fabric/ImageRequestParams.cpp +26 -0
  75. package/Microsoft.ReactNative/Fabric/WindowsImageManager.cpp +47 -8
  76. package/Microsoft.ReactNative/Fabric/WindowsImageManager.h +10 -1
  77. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/CompositionAccessibilityProps.h +67 -0
  78. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp +22 -4
  79. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.h +15 -2
  80. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp +20 -0
  81. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h +5 -0
  82. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/MouseEvent.h +20 -0
  83. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/HostPlatformColor.h +5 -8
  84. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorParser.h +1 -2
  85. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +247 -45
  86. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h +15 -0
  87. package/Microsoft.ReactNative/Fabric/platform/react/threading/MessageQueueThreadImpl.cpp +39 -0
  88. package/Microsoft.ReactNative/Fabric/platform/react/threading/MessageQueueThreadImpl.h +54 -0
  89. package/Microsoft.ReactNative/Fabric/platform/react/threading/TaskDispatchThread.cpp +126 -0
  90. package/Microsoft.ReactNative/Fabric/platform/react/threading/TaskDispatchThread.h +73 -0
  91. package/Microsoft.ReactNative/IReactContext.cpp +17 -0
  92. package/Microsoft.ReactNative/IReactContext.h +1 -0
  93. package/Microsoft.ReactNative/IReactContext.idl +18 -1
  94. package/Microsoft.ReactNative/IReactDispatcher.idl +1 -0
  95. package/Microsoft.ReactNative/IReactModuleBuilder.cpp +12 -0
  96. package/Microsoft.ReactNative/IReactModuleBuilder.h +2 -0
  97. package/Microsoft.ReactNative/IReactModuleBuilder.idl +8 -0
  98. package/Microsoft.ReactNative/JsiApi.cpp +10 -2
  99. package/Microsoft.ReactNative/JsiApi.h +1 -0
  100. package/Microsoft.ReactNative/JsiApi.idl +1 -0
  101. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +0 -3
  102. package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp +2 -3
  103. package/Microsoft.ReactNative/Modules/AlertModule.cpp +7 -12
  104. package/Microsoft.ReactNative/Modules/Animated/AnimationDriver.cpp +2 -1
  105. package/Microsoft.ReactNative/Modules/Animated/NativeAnimatedModule.cpp +4 -8
  106. package/Microsoft.ReactNative/Modules/AppStateModule.cpp +2 -2
  107. package/Microsoft.ReactNative/Modules/ClipboardModule.cpp +6 -8
  108. package/Microsoft.ReactNative/Modules/ClipboardModule.h +1 -1
  109. package/Microsoft.ReactNative/Modules/ImageViewManagerModule.cpp +6 -15
  110. package/Microsoft.ReactNative/Modules/NativeUIManager.cpp +13 -24
  111. package/Microsoft.ReactNative/QuirkSettings.cpp +0 -16
  112. package/Microsoft.ReactNative/QuirkSettings.h +0 -3
  113. package/Microsoft.ReactNative/ReactHost/ReactHost.cpp +11 -1
  114. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +78 -68
  115. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +1 -2
  116. package/Microsoft.ReactNative/ReactInstanceSettings.cpp +12 -0
  117. package/Microsoft.ReactNative/ReactInstanceSettings.h +2 -0
  118. package/Microsoft.ReactNative/ReactInstanceSettings.idl +6 -0
  119. package/Microsoft.ReactNative/ReactNativeIsland.idl +3 -0
  120. package/Microsoft.ReactNative/ReactSupport.cpp +44 -11
  121. package/Microsoft.ReactNative/RedBox.cpp +30 -1
  122. package/Microsoft.ReactNative/SchedulerSettings.cpp +4 -4
  123. package/Microsoft.ReactNative/SchedulerSettings.h +1 -1
  124. package/Microsoft.ReactNative/TurboModulesProvider.cpp +30 -12
  125. package/Microsoft.ReactNative/Utils/ImageUtils.h +1 -0
  126. package/Microsoft.ReactNative/Utils/LocalBundleReader.cpp +37 -31
  127. package/Microsoft.ReactNative.Cxx/ApiLoaders/JSRuntimeApi.cpp +1 -0
  128. package/Microsoft.ReactNative.Cxx/ApiLoaders/JSRuntimeApi.inc +2 -0
  129. package/Microsoft.ReactNative.Cxx/ApiLoaders/NodeApi_posix.cpp +1 -1
  130. package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.cpp +94 -27
  131. package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.h +27 -6
  132. package/Microsoft.ReactNative.Cxx/JSI/JsiApiContext.cpp +45 -11
  133. package/Microsoft.ReactNative.Cxx/JSI/JsiApiContext.h +6 -0
  134. package/Microsoft.ReactNative.Cxx/JSI/decorator.h +220 -0
  135. package/Microsoft.ReactNative.Cxx/JSI/instrumentation.h +28 -0
  136. package/Microsoft.ReactNative.Cxx/JSI/jsi-inl.h +6 -0
  137. package/Microsoft.ReactNative.Cxx/JSI/jsi.cpp +241 -4
  138. package/Microsoft.ReactNative.Cxx/JSI/jsi.h +207 -19
  139. package/Microsoft.ReactNative.Cxx/JSValue.cpp +19 -3
  140. package/Microsoft.ReactNative.Cxx/JSValue.h +15 -7
  141. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +2 -2
  142. package/Microsoft.ReactNative.Cxx/NativeModules.h +60 -2
  143. package/Microsoft.ReactNative.Cxx/NodeApiJsiRuntime.cpp +1267 -614
  144. package/Microsoft.ReactNative.Cxx/NodeApiJsiRuntime.h +4 -2
  145. package/Microsoft.ReactNative.Cxx/ReactContext.h +7 -0
  146. package/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp +11 -13
  147. package/Microsoft.ReactNative.Cxx/TurboModuleProvider.h +2 -3
  148. package/Microsoft.ReactNative.Cxx/node-api/js_native_api.h +81 -20
  149. package/Microsoft.ReactNative.Cxx/node-api/js_native_api_types.h +47 -2
  150. package/Microsoft.ReactNative.Cxx/node-api/js_runtime_api.h +13 -0
  151. package/Microsoft.ReactNative.Cxx/stubs/glog/logging.h +1 -1
  152. package/Microsoft.ReactNative.Managed/ReactContext.cs +3 -1
  153. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  154. package/PropertySheets/JSEngine.props +1 -1
  155. package/PropertySheets/React.Cpp.props +2 -1
  156. package/PropertySheets/WebView2.props +1 -1
  157. package/PropertySheets/WinUI.props +2 -2
  158. package/ReactCommon/TEMP_UntilReactCommonUpdate/jserrorhandler/JsErrorHandler.cpp +429 -0
  159. package/ReactCommon/cgmanifest.json +1 -1
  160. package/Shared/HermesRuntimeHolder.cpp +6 -0
  161. package/Shared/JSI/ChakraRuntime.cpp +4 -0
  162. package/Shared/JSI/ChakraRuntime.h +2 -0
  163. package/Shared/Modules/BlobModule.cpp +14 -16
  164. package/Shared/Modules/BlobModule.h +3 -1
  165. package/Shared/Shared.vcxitems +11 -7
  166. package/Shared/Shared.vcxitems.filters +6 -1
  167. package/Shared/TurboModuleManager.cpp +0 -15
  168. package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +6 -6
  169. package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +6 -6
  170. package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +6 -6
  171. package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +6 -6
  172. package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +6 -6
  173. package/codegen/react/components/rnwcore/AndroidSwitch.g.h +6 -6
  174. package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +6 -6
  175. package/codegen/react/components/rnwcore/InputAccessory.g.h +6 -6
  176. package/codegen/react/components/rnwcore/ModalHostView.g.h +11 -7
  177. package/codegen/react/components/rnwcore/Props.cpp +2 -1
  178. package/codegen/react/components/rnwcore/Props.h +1 -0
  179. package/codegen/react/components/rnwcore/PullToRefreshView.g.h +6 -6
  180. package/codegen/react/components/rnwcore/SafeAreaView.g.h +6 -6
  181. package/codegen/react/components/rnwcore/Switch.g.h +6 -6
  182. package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +6 -6
  183. package/index.windows.js +4 -2
  184. package/package.json +3 -4
  185. package/src/private/specs/components/RCTModalHostViewNativeComponent.js +8 -0
  186. package/stubs/glog/logging.h +1 -1
  187. package/Microsoft.ReactNative/JSDispatcherWriter.h +0 -47
  188. package/Microsoft.ReactNative/SynchronousEventBeat.cpp +0 -51
  189. package/Microsoft.ReactNative/SynchronousEventBeat.h +0 -31
@@ -43,6 +43,7 @@ constexpr float loadingActivitySize = 12.0f;
43
43
  constexpr float loadingActivityHorizontalOffset = 16.0f;
44
44
  constexpr float loadingBarHeight = 36.0f;
45
45
  constexpr float loadingBarFontSize = 20.0f;
46
+ constexpr float loadingBarMinFontSize = 8.0f;
46
47
  constexpr float loadingTextHorizontalOffset = 48.0f;
47
48
 
48
49
  //! This class ensures that we access ReactRootView from UI thread.
@@ -195,6 +196,8 @@ void ReactNativeIsland::ReactViewHost(winrt::Microsoft::ReactNative::IReactViewH
195
196
  return;
196
197
  }
197
198
 
199
+ m_props = nullptr;
200
+
198
201
  if (m_reactViewHost) {
199
202
  UninitRootView();
200
203
  m_reactViewHost.DetachViewInstance();
@@ -374,11 +377,12 @@ winrt::IInspectable ReactNativeIsland::GetUiaProvider() noexcept {
374
377
  if (m_uiaProvider == nullptr) {
375
378
  m_uiaProvider =
376
379
  winrt::make<winrt::Microsoft::ReactNative::implementation::CompositionRootAutomationProvider>(*this);
377
- if (m_hwnd && !m_island) {
380
+ if (m_hwnd || m_island) {
378
381
  auto pRootProvider =
379
382
  static_cast<winrt::Microsoft::ReactNative::implementation::CompositionRootAutomationProvider *>(
380
383
  m_uiaProvider.as<IRawElementProviderSimple>().get());
381
384
  if (pRootProvider != nullptr) {
385
+ pRootProvider->SetIsland(m_island);
382
386
  pRootProvider->SetHwnd(m_hwnd);
383
387
  }
384
388
  }
@@ -517,13 +521,6 @@ void ReactNativeIsland::UpdateRootViewInternal() noexcept {
517
521
  }
518
522
  }
519
523
 
520
- struct AutoMRE {
521
- ~AutoMRE() {
522
- mre.Set();
523
- }
524
- Mso::ManualResetEvent mre;
525
- };
526
-
527
524
  void ReactNativeIsland::UninitRootView() noexcept {
528
525
  if (!m_isInitialized) {
529
526
  return;
@@ -533,20 +530,9 @@ void ReactNativeIsland::UninitRootView() noexcept {
533
530
  if (m_context.Handle().LoadingState() == winrt::Microsoft::ReactNative::LoadingState::HasError)
534
531
  return;
535
532
 
536
- auto uiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
537
- winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()));
538
- uiManager->stopSurface(static_cast<facebook::react::SurfaceId>(RootTag()));
539
-
540
- // This is needed to ensure that the unmount JS logic is completed before the the instance is shutdown during
541
- // instance destruction. Aligns with similar code in ReactInstanceWin::DetachRootView for paper Future: Instead
542
- // this method should return a Promise, which should be resolved when the JS logic is complete. The task will auto
543
- // set the event on destruction to ensure that the event is set if the JS Queue has already been shutdown
544
- Mso::ManualResetEvent mre;
545
- m_context.JSDispatcher().Post([autoMRE = std::make_unique<AutoMRE>(AutoMRE{mre})]() {});
546
- mre.Wait();
547
-
548
- // Paper version gives the JS thread time to finish executing - Is this needed?
549
- // m_jsMessageThread.Load()->runOnQueueSync([]() {});
533
+ if (auto uiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
534
+ winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties())))
535
+ uiManager->stopSurface(static_cast<facebook::react::SurfaceId>(RootTag()));
550
536
  }
551
537
 
552
538
  m_rootTag = -1;
@@ -577,7 +563,9 @@ void ReactNativeIsland::ShowInstanceLoaded() noexcept {
577
563
  winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()));
578
564
 
579
565
  m_rootTag = ::Microsoft::ReactNative::getNextRootViewTag();
580
- auto initProps = DynamicWriter::ToDynamic(Mso::Copy(m_reactViewOptions.InitialProps()));
566
+
567
+ auto initProps =
568
+ m_props.isNull() ? DynamicWriter::ToDynamic(Mso::Copy(m_reactViewOptions.InitialProps())) : m_props;
581
569
  if (initProps.isNull()) {
582
570
  initProps = folly::dynamic::object();
583
571
  }
@@ -606,6 +594,14 @@ facebook::react::AttributedStringBox CreateLoadingAttributedString() noexcept {
606
594
  return facebook::react::AttributedStringBox{attributedString};
607
595
  }
608
596
 
597
+ facebook::react::ParagraphAttributes CreateLoadingParagraphAttributes() noexcept {
598
+ facebook::react::ParagraphAttributes pa;
599
+ pa.adjustsFontSizeToFit = true;
600
+ pa.minimumFontSize = loadingBarMinFontSize;
601
+ pa.maximumFontSize = loadingBarFontSize;
602
+ return pa;
603
+ }
604
+
609
605
  facebook::react::Size ReactNativeIsland::MeasureLoading(
610
606
  const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints) const noexcept {
611
607
  facebook::react::LayoutConstraints fbLayoutConstraints;
@@ -614,7 +610,7 @@ facebook::react::Size ReactNativeIsland::MeasureLoading(
614
610
  auto attributedStringBox = CreateLoadingAttributedString();
615
611
  winrt::com_ptr<::IDWriteTextLayout> textLayout;
616
612
  facebook::react::TextLayoutManager::GetTextLayout(
617
- attributedStringBox, {} /*paragraphAttributes*/, fbLayoutConstraints, textLayout);
613
+ attributedStringBox, CreateLoadingParagraphAttributes(), fbLayoutConstraints, textLayout);
618
614
 
619
615
  DWRITE_TEXT_METRICS tm;
620
616
  winrt::check_hresult(textLayout->GetMetrics(&tm));
@@ -696,7 +692,7 @@ Composition::Experimental::IDrawingSurfaceBrush ReactNativeIsland::CreateLoading
696
692
 
697
693
  winrt::com_ptr<::IDWriteTextLayout> textLayout;
698
694
  facebook::react::TextLayoutManager::GetTextLayout(
699
- attributedStringBox, {} /*paragraphAttributes*/, constraints, textLayout);
695
+ attributedStringBox, CreateLoadingParagraphAttributes(), constraints, textLayout);
700
696
 
701
697
  DWRITE_TEXT_METRICS tm;
702
698
  textLayout->GetMetrics(&tm);
@@ -778,7 +774,7 @@ winrt::Windows::Foundation::Size ReactNativeIsland::Measure(
778
774
  facebook::react::LayoutConstraints constraints;
779
775
  ApplyConstraints(layoutConstraints, constraints);
780
776
 
781
- if (m_isInitialized && m_rootTag != -1) {
777
+ if (m_isInitialized && m_rootTag != -1 && m_hasRenderedVisual) {
782
778
  if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
783
779
  winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) {
784
780
  facebook::react::LayoutContext context;
@@ -809,7 +805,7 @@ void ReactNativeIsland::Arrange(
809
805
  facebook::react::LayoutConstraints fbLayoutConstraints;
810
806
  ApplyConstraints(layoutConstraints, fbLayoutConstraints);
811
807
 
812
- if (m_isInitialized && m_rootTag != -1 && !m_isFragment) {
808
+ if (m_isInitialized && m_rootTag != -1 && !m_isFragment && m_hasRenderedVisual) {
813
809
  if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
814
810
  winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) {
815
811
  facebook::react::LayoutContext context;
@@ -871,14 +867,7 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
871
867
  winrt::Microsoft::UI::Content::ContentIsland const &,
872
868
  winrt::Microsoft::UI::Content::ContentIslandAutomationProviderRequestedEventArgs const &args) {
873
869
  if (auto pThis = weakThis.get()) {
874
- auto provider = pThis->GetUiaProvider();
875
- auto pRootProvider =
876
- static_cast<winrt::Microsoft::ReactNative::implementation::CompositionRootAutomationProvider *>(
877
- provider.as<IRawElementProviderSimple>().get());
878
- if (pRootProvider != nullptr) {
879
- pRootProvider->SetIsland(pThis->m_island);
880
- }
881
- args.AutomationProvider(std::move(provider));
870
+ args.AutomationProvider(pThis->GetUiaProvider());
882
871
  args.Handled(true);
883
872
  }
884
873
  });
@@ -900,16 +889,6 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
900
889
  if (args.DidLayoutDirectionChange()) {
901
890
  pThis->Arrange(pThis->m_layoutConstraints, pThis->m_viewportOffset);
902
891
  }
903
- #ifndef USE_EXPERIMENTAL_WINUI3 // Use this in place of Connected/Disconnected events for now. -- Its not quite what we
904
- // want, but it will do for now.
905
- if (args.DidSiteVisibleChange()) {
906
- if (island.IsSiteVisible()) {
907
- pThis->OnMounted();
908
- } else {
909
- pThis->OnUnmounted();
910
- }
911
- }
912
- #endif
913
892
  }
914
893
  });
915
894
  #ifdef USE_EXPERIMENTAL_WINUI3
@@ -965,6 +944,24 @@ void ReactNativeIsland::OnUnmounted() noexcept {
965
944
  }
966
945
  }
967
946
 
947
+ void ReactNativeIsland::SetProperties(winrt::Microsoft::ReactNative::JSValueArgWriter props) noexcept {
948
+ auto initProps = DynamicWriter::ToDynamic(props);
949
+ if (initProps.isNull()) {
950
+ initProps = folly::dynamic::object();
951
+ }
952
+
953
+ if (m_isJSViewAttached) {
954
+ if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
955
+ winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) {
956
+ initProps["concurrentRoot"] = true;
957
+ fabricuiManager->setProps(static_cast<facebook::react::SurfaceId>(m_rootTag), initProps);
958
+ return;
959
+ }
960
+ }
961
+
962
+ m_props = initProps;
963
+ }
964
+
968
965
  winrt::com_ptr<winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView>
969
966
  ReactNativeIsland::GetComponentView() noexcept {
970
967
  if (auto portal = m_portal.get()) {
@@ -979,10 +976,10 @@ ReactNativeIsland::GetComponentView() noexcept {
979
976
 
980
977
  if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
981
978
  winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) {
982
- auto rootComponentViewDescriptor = fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(
983
- static_cast<facebook::react::SurfaceId>(m_rootTag));
984
- return rootComponentViewDescriptor.view
985
- .as<winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView>();
979
+ if (auto view = fabricuiManager->GetViewRegistry().findComponentViewWithTag(
980
+ static_cast<facebook::react::SurfaceId>(m_rootTag))) {
981
+ return view.as<winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView>();
982
+ }
986
983
  }
987
984
  return nullptr;
988
985
  }
@@ -76,6 +76,8 @@ struct ReactNativeIsland
76
76
  float ScaleFactor() noexcept;
77
77
  void ScaleFactor(float value) noexcept;
78
78
 
79
+ void SetProperties(winrt::Microsoft::ReactNative::JSValueArgWriter props) noexcept;
80
+
79
81
  float FontSizeMultiplier() const noexcept;
80
82
 
81
83
  winrt::event_token SizeChanged(
@@ -154,11 +156,14 @@ struct ReactNativeIsland
154
156
  bool m_isJSViewAttached{false};
155
157
  bool m_hasRenderedVisual{false};
156
158
  bool m_showingLoadingUI{false};
157
- bool m_mounted{false};
159
+ bool m_mounted{true};
158
160
  winrt::weak_ref<winrt::Microsoft::ReactNative::Composition::PortalComponentView> m_portal{nullptr};
159
161
  IReactDispatcher m_uiDispatcher{nullptr};
160
162
  winrt::IInspectable m_uiaProvider{nullptr};
161
163
 
164
+ // If SetProps is called before the surface is loaded, store it locally to use on start
165
+ folly::dynamic m_props;
166
+
162
167
  // This is the surfaceId that this island belongs to.
163
168
  // In the case of portal content root, this will be the surfaceId that contains the portal.
164
169
  int64_t m_rootTag{-1};
@@ -76,7 +76,10 @@ void RootComponentView::updateLayoutMetrics(
76
76
  winrt::Microsoft::ReactNative::ComponentView RootComponentView::GetFocusedComponent() noexcept {
77
77
  return m_focusedComponent;
78
78
  }
79
- void RootComponentView::SetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &value) noexcept {
79
+
80
+ void RootComponentView::SetFocusedComponent(
81
+ const winrt::Microsoft::ReactNative::ComponentView &value,
82
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction) noexcept {
80
83
  if (m_focusedComponent == value)
81
84
  return;
82
85
 
@@ -90,11 +93,10 @@ void RootComponentView::SetFocusedComponent(const winrt::Microsoft::ReactNative:
90
93
  if (auto rootView = m_wkRootView.get()) {
91
94
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(rootView)->TrySetFocus();
92
95
  }
93
- auto args = winrt::make<winrt::Microsoft::ReactNative::implementation::GotFocusEventArgs>(value);
96
+ m_focusedComponent = value;
97
+ auto args = winrt::make<winrt::Microsoft::ReactNative::implementation::GotFocusEventArgs>(value, direction);
94
98
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(value)->onGotFocus(args);
95
99
  }
96
-
97
- m_focusedComponent = value;
98
100
  }
99
101
 
100
102
  bool RootComponentView::NavigateFocus(const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept {
@@ -118,7 +120,8 @@ bool RootComponentView::NavigateFocus(const winrt::Microsoft::ReactNative::Focus
118
120
 
119
121
  bool RootComponentView::TrySetFocusedComponent(
120
122
  const winrt::Microsoft::ReactNative::ComponentView &view,
121
- winrt::Microsoft::ReactNative::FocusNavigationDirection direction) noexcept {
123
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
124
+ bool forceNoSelectionIfCannotMove /*= false*/) noexcept {
122
125
  auto target = view;
123
126
  auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
124
127
  if (selfView && !selfView->focusable()) {
@@ -126,7 +129,7 @@ bool RootComponentView::TrySetFocusedComponent(
126
129
  direction == winrt::Microsoft::ReactNative::FocusNavigationDirection::Previous)
127
130
  ? FocusManager::FindLastFocusableElement(target)
128
131
  : FocusManager::FindFirstFocusableElement(target);
129
- if (!target)
132
+ if (!target && !forceNoSelectionIfCannotMove)
130
133
  return false;
131
134
  selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
132
135
  }
@@ -151,7 +154,9 @@ bool RootComponentView::TrySetFocusedComponent(
151
154
 
152
155
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(losingFocusArgs.NewFocusedComponent())
153
156
  ->rootComponentView()
154
- ->SetFocusedComponent(gettingFocusArgs.NewFocusedComponent());
157
+ ->SetFocusedComponent(gettingFocusArgs.NewFocusedComponent(), direction);
158
+ } else {
159
+ SetFocusedComponent(nullptr, direction);
155
160
  }
156
161
 
157
162
  return true;
@@ -241,7 +246,7 @@ void RootComponentView::start(const winrt::Microsoft::ReactNative::ReactNativeIs
241
246
  }
242
247
 
243
248
  void RootComponentView::stop() noexcept {
244
- SetFocusedComponent(nullptr);
249
+ SetFocusedComponent(nullptr, winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
245
250
  if (m_visualAddedToIsland) {
246
251
  if (auto rootView = m_wkRootView.get()) {
247
252
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(rootView)->RemoveRenderedVisual(
@@ -27,10 +27,13 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
27
27
  winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept;
28
28
 
29
29
  winrt::Microsoft::ReactNative::ComponentView GetFocusedComponent() noexcept;
30
- void SetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &value) noexcept;
30
+ void SetFocusedComponent(
31
+ const winrt::Microsoft::ReactNative::ComponentView &value,
32
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction) noexcept;
31
33
  bool TrySetFocusedComponent(
32
34
  const winrt::Microsoft::ReactNative::ComponentView &view,
33
- winrt::Microsoft::ReactNative::FocusNavigationDirection direction) noexcept;
35
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
36
+ bool forceNoSelectionIfCannotMove = false) noexcept;
34
37
 
35
38
  bool NavigateFocus(const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept;
36
39
 
@@ -81,9 +81,12 @@ struct ScrollBarComponent {
81
81
  }
82
82
 
83
83
  void ContentSize(winrt::Windows::Foundation::Size contentSize) noexcept {
84
+ if (m_contentSize == contentSize) {
85
+ return;
86
+ }
84
87
  m_contentSize = contentSize;
85
88
  updateThumb();
86
- updateVisibility();
89
+ updateVisibility(m_visible);
87
90
  }
88
91
 
89
92
  void updateTrack() noexcept {
@@ -108,10 +111,22 @@ struct ScrollBarComponent {
108
111
 
109
112
  updateTrack();
110
113
  updateThumb();
111
- updateVisibility();
114
+ updateVisibility(m_visible);
112
115
  }
113
116
 
114
- void updateVisibility() noexcept {
117
+ void updateVisibility(bool visible) noexcept {
118
+ if ((m_size.Width <= 0.0f && m_size.Height <= 0.0f) ||
119
+ (m_contentSize.Width <= 0.0f && m_contentSize.Height <= 0.0f)) {
120
+ m_rootVisual.IsVisible(false);
121
+ return;
122
+ }
123
+
124
+ if (!visible) {
125
+ m_visible = false;
126
+ m_rootVisual.IsVisible(visible);
127
+ return;
128
+ }
129
+
115
130
  bool newVisibility = false;
116
131
  if (m_vertical) {
117
132
  newVisibility = (m_contentSize.Height > m_size.Height);
@@ -119,10 +134,8 @@ struct ScrollBarComponent {
119
134
  newVisibility = (m_contentSize.Width > m_size.Width);
120
135
  }
121
136
 
122
- if (newVisibility != m_visible) {
123
- m_visible = newVisibility;
124
- m_rootVisual.IsVisible(m_visible);
125
- }
137
+ m_visible = newVisibility;
138
+ m_rootVisual.IsVisible(m_visible);
126
139
  }
127
140
 
128
141
  void updateRootAndArrowVisualOffsets() noexcept {
@@ -561,7 +574,7 @@ struct ScrollBarComponent {
561
574
  winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext m_compContext;
562
575
  winrt::Microsoft::ReactNative::ReactContext m_reactContext;
563
576
  const bool m_vertical;
564
- bool m_visible{false};
577
+ bool m_visible{true};
565
578
  bool m_shy{false};
566
579
  int m_thumbSize{0};
567
580
  float m_arrowSize{0};
@@ -753,6 +766,44 @@ void ScrollViewComponentView::updateProps(
753
766
  if (!oldProps || oldViewProps.horizontal != newViewProps.horizontal) {
754
767
  m_scrollVisual.Horizontal(newViewProps.horizontal);
755
768
  }
769
+
770
+ if (!oldProps || oldViewProps.showsHorizontalScrollIndicator != newViewProps.showsHorizontalScrollIndicator) {
771
+ updateShowsHorizontalScrollIndicator(newViewProps.showsHorizontalScrollIndicator);
772
+ }
773
+
774
+ if (!oldProps || oldViewProps.showsVerticalScrollIndicator != newViewProps.showsVerticalScrollIndicator) {
775
+ updateShowsVerticalScrollIndicator(newViewProps.showsVerticalScrollIndicator);
776
+ }
777
+
778
+ if (!oldProps || oldViewProps.decelerationRate != newViewProps.decelerationRate) {
779
+ updateDecelerationRate(newViewProps.decelerationRate);
780
+ }
781
+
782
+ if (!oldProps || oldViewProps.scrollEventThrottle != newViewProps.scrollEventThrottle) {
783
+ // Zero means "send value only once per significant logical event".
784
+ // Prop value is in milliseconds.
785
+ auto throttleInSeconds = newViewProps.scrollEventThrottle / 1000.0;
786
+ auto msPerFrame = 1.0 / 60.0;
787
+ if (throttleInSeconds < 0) {
788
+ m_scrollEventThrottle = INFINITY;
789
+ } else if (throttleInSeconds <= msPerFrame) {
790
+ m_scrollEventThrottle = 0;
791
+ } else {
792
+ m_scrollEventThrottle = throttleInSeconds;
793
+ }
794
+ }
795
+
796
+ if (oldViewProps.maximumZoomScale != newViewProps.maximumZoomScale) {
797
+ m_scrollVisual.SetMaximumZoomScale(newViewProps.maximumZoomScale);
798
+ }
799
+
800
+ if (oldViewProps.minimumZoomScale != newViewProps.minimumZoomScale) {
801
+ m_scrollVisual.SetMinimumZoomScale(newViewProps.minimumZoomScale);
802
+ }
803
+
804
+ if (oldViewProps.zoomScale != newViewProps.zoomScale) {
805
+ m_scrollVisual.Scale({newViewProps.zoomScale, newViewProps.zoomScale, newViewProps.zoomScale});
806
+ }
756
807
  }
757
808
 
758
809
  void ScrollViewComponentView::updateState(
@@ -784,14 +835,15 @@ void ScrollViewComponentView::updateLayoutMetrics(
784
835
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept {
785
836
  // Set Position & Size Properties
786
837
  ensureVisual();
787
-
788
- m_verticalScrollbarComponent->updateLayoutMetrics(layoutMetrics);
789
- m_horizontalScrollbarComponent->updateLayoutMetrics(layoutMetrics);
790
- base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
791
- m_scrollVisual.Size(
792
- {layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor,
793
- layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor});
794
- updateContentVisualSize();
838
+ if (oldLayoutMetrics != layoutMetrics) {
839
+ m_verticalScrollbarComponent->updateLayoutMetrics(layoutMetrics);
840
+ m_horizontalScrollbarComponent->updateLayoutMetrics(layoutMetrics);
841
+ base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
842
+ m_scrollVisual.Size(
843
+ {layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor,
844
+ layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor});
845
+ updateContentVisualSize();
846
+ }
795
847
  }
796
848
 
797
849
  void ScrollViewComponentView::updateContentVisualSize() noexcept {
@@ -962,6 +1014,8 @@ bool ScrollViewComponentView::scrollToEnd(bool animate) noexcept {
962
1014
 
963
1015
  auto x = (m_contentSize.width - m_layoutMetrics.frame.size.width) * m_layoutMetrics.pointScaleFactor;
964
1016
  auto y = (m_contentSize.height - m_layoutMetrics.frame.size.height) * m_layoutMetrics.pointScaleFactor;
1017
+ // Ensure at least one scroll event will fire
1018
+ m_allowNextScrollNoMatterWhat = true;
965
1019
  m_scrollVisual.TryUpdatePosition({static_cast<float>(x), static_cast<float>(y), 0.0f}, animate);
966
1020
  return true;
967
1021
  }
@@ -1189,6 +1243,23 @@ void ScrollViewComponentView::StartBringIntoView(
1189
1243
  }
1190
1244
  }
1191
1245
 
1246
+ facebook::react::ScrollViewEventEmitter::Metrics ScrollViewComponentView::getScrollMetrics(
1247
+ facebook::react::SharedViewEventEmitter const &eventEmitter,
1248
+ winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) noexcept {
1249
+ facebook::react::ScrollViewEventEmitter::Metrics scrollMetrics{};
1250
+ if (eventEmitter) {
1251
+ scrollMetrics.containerSize.height = m_layoutMetrics.frame.size.height;
1252
+ scrollMetrics.containerSize.width = m_layoutMetrics.frame.size.width;
1253
+ scrollMetrics.contentOffset.x = args.Position().x / m_layoutMetrics.pointScaleFactor;
1254
+ scrollMetrics.contentOffset.y = args.Position().y / m_layoutMetrics.pointScaleFactor;
1255
+ scrollMetrics.zoomScale = 1.0;
1256
+ scrollMetrics.contentSize.height = std::max(m_contentSize.height, m_layoutMetrics.frame.size.height);
1257
+ scrollMetrics.contentSize.width = std::max(m_contentSize.width, m_layoutMetrics.frame.size.width);
1258
+ }
1259
+
1260
+ return scrollMetrics;
1261
+ }
1262
+
1192
1263
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ScrollViewComponentView::createVisual() noexcept {
1193
1264
  auto visual = m_compContext.CreateSpriteVisual();
1194
1265
  m_scrollVisual = m_compContext.CreateScrollerVisual();
@@ -1202,21 +1273,52 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ScrollViewComp
1202
1273
  [this](
1203
1274
  winrt::IInspectable const & /*sender*/,
1204
1275
  winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) {
1276
+ auto now = std::chrono::steady_clock::now();
1277
+ auto elapsed = std::chrono::duration_cast<std::chrono::duration<double>>(now - m_lastScrollEventTime).count();
1278
+
1279
+ if (m_allowNextScrollNoMatterWhat ||
1280
+ (m_scrollEventThrottle < std::max(std::chrono::duration<double>(0.017).count(), elapsed))) {
1281
+ updateStateWithContentOffset();
1282
+ auto eventEmitter = GetEventEmitter();
1283
+ if (eventEmitter) {
1284
+ auto scrollMetrics = getScrollMetrics(eventEmitter, args);
1285
+ std::static_pointer_cast<facebook::react::ScrollViewEventEmitter const>(eventEmitter)
1286
+ ->onScroll(scrollMetrics);
1287
+ m_lastScrollEventTime = now;
1288
+ m_allowNextScrollNoMatterWhat = false;
1289
+ }
1290
+ }
1291
+ });
1292
+
1293
+ m_scrollBeginDragRevoker = m_scrollVisual.ScrollBeginDrag(
1294
+ winrt::auto_revoke,
1295
+ [this](
1296
+ winrt::IInspectable const & /*sender*/,
1297
+ winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) {
1298
+ m_allowNextScrollNoMatterWhat = true; // Ensure next scroll event is recorded, regardless of throttle
1205
1299
  updateStateWithContentOffset();
1206
1300
  auto eventEmitter = GetEventEmitter();
1207
1301
  if (eventEmitter) {
1208
- facebook::react::ScrollViewEventEmitter::Metrics scrollMetrics;
1209
- scrollMetrics.containerSize.height = m_layoutMetrics.frame.size.height;
1210
- scrollMetrics.containerSize.width = m_layoutMetrics.frame.size.width;
1211
- scrollMetrics.contentOffset.x = args.Position().x / m_layoutMetrics.pointScaleFactor;
1212
- scrollMetrics.contentOffset.y = args.Position().y / m_layoutMetrics.pointScaleFactor;
1213
- scrollMetrics.zoomScale = 1.0;
1214
- scrollMetrics.contentSize.height = std::max(m_contentSize.height, m_layoutMetrics.frame.size.height);
1215
- scrollMetrics.contentSize.width = std::max(m_contentSize.width, m_layoutMetrics.frame.size.width);
1302
+ auto scrollMetrics = getScrollMetrics(eventEmitter, args);
1216
1303
  std::static_pointer_cast<facebook::react::ScrollViewEventEmitter const>(eventEmitter)
1217
- ->onScroll(scrollMetrics);
1304
+ ->onScrollBeginDrag(scrollMetrics);
1218
1305
  }
1219
1306
  });
1307
+
1308
+ m_scrollEndDragRevoker = m_scrollVisual.ScrollEndDrag(
1309
+ winrt::auto_revoke,
1310
+ [this](
1311
+ winrt::IInspectable const & /*sender*/,
1312
+ winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) {
1313
+ updateStateWithContentOffset();
1314
+ auto eventEmitter = GetEventEmitter();
1315
+ if (eventEmitter) {
1316
+ auto scrollMetrics = getScrollMetrics(eventEmitter, args);
1317
+ std::static_pointer_cast<facebook::react::ScrollViewEventEmitter const>(eventEmitter)
1318
+ ->onScrollEndDrag(scrollMetrics);
1319
+ }
1320
+ });
1321
+
1220
1322
  return visual;
1221
1323
  }
1222
1324
 
@@ -1294,4 +1396,23 @@ double ScrollViewComponentView::getHorizontalSize() noexcept {
1294
1396
  return std::min((m_layoutMetrics.frame.size.width / m_contentSize.width * 100.0), 100.0);
1295
1397
  }
1296
1398
 
1399
+ void ScrollViewComponentView::updateShowsHorizontalScrollIndicator(bool value) noexcept {
1400
+ if (value) {
1401
+ m_horizontalScrollbarComponent->updateVisibility(true);
1402
+ } else {
1403
+ m_horizontalScrollbarComponent->updateVisibility(false);
1404
+ }
1405
+ }
1406
+
1407
+ void ScrollViewComponentView::updateShowsVerticalScrollIndicator(bool value) noexcept {
1408
+ if (value) {
1409
+ m_verticalScrollbarComponent->updateVisibility(true);
1410
+ } else {
1411
+ m_verticalScrollbarComponent->updateVisibility(false);
1412
+ }
1413
+ }
1414
+
1415
+ void ScrollViewComponentView::updateDecelerationRate(float value) noexcept {
1416
+ m_scrollVisual.SetDecelerationRate({value, value, value});
1417
+ }
1297
1418
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -119,6 +119,7 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
119
119
  double getHorizontalSize() noexcept;
120
120
 
121
121
  private:
122
+ void updateDecelerationRate(float value) noexcept;
122
123
  void updateContentVisualSize() noexcept;
123
124
  bool scrollToEnd(bool animate) noexcept;
124
125
  bool scrollToStart(bool animate) noexcept;
@@ -128,6 +129,11 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
128
129
  bool scrollRight(float delta, bool animate) noexcept;
129
130
  void updateBackgroundColor(const facebook::react::SharedColor &color) noexcept;
130
131
  void updateStateWithContentOffset() noexcept;
132
+ facebook::react::ScrollViewEventEmitter::Metrics getScrollMetrics(
133
+ facebook::react::SharedViewEventEmitter const &eventEmitter,
134
+ winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) noexcept;
135
+ void updateShowsHorizontalScrollIndicator(bool value) noexcept;
136
+ void updateShowsVerticalScrollIndicator(bool value) noexcept;
131
137
 
132
138
  facebook::react::Size m_contentSize;
133
139
  winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual m_scrollVisual{nullptr};
@@ -135,6 +141,11 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
135
141
  std::shared_ptr<ScrollBarComponent> m_verticalScrollbarComponent{nullptr};
136
142
  winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollPositionChanged_revoker
137
143
  m_scrollPositionChangedRevoker{};
144
+ winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollBeginDrag_revoker
145
+ m_scrollBeginDragRevoker{};
146
+
147
+ winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollEndDrag_revoker
148
+ m_scrollEndDragRevoker{};
138
149
 
139
150
  float m_zoomFactor{1.0f};
140
151
  bool m_isScrollingFromInertia = false;
@@ -142,6 +153,9 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
142
153
  bool m_isHorizontal = false;
143
154
  bool m_changeViewAfterLoaded = false;
144
155
  bool m_dismissKeyboardOnDrag = false;
156
+ double m_scrollEventThrottle{0.0};
157
+ bool m_allowNextScrollNoMatterWhat{false};
158
+ std::chrono::steady_clock::time_point m_lastScrollEventTime{};
145
159
  std::shared_ptr<facebook::react::ScrollViewShadowNode::ConcreteState const> m_state;
146
160
  };
147
161