react-native-windows 0.76.10 → 0.76.12

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 (58) hide show
  1. package/Directory.Build.props +2 -2
  2. package/Folly/TEMP_UntilFollyUpdate/json.cpp +4 -0
  3. package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.cpp +23 -15
  4. package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.h +5 -5
  5. package/Folly/cgmanifest.json +1 -1
  6. package/Libraries/Components/Button.windows.js +3 -0
  7. package/Libraries/Components/ScrollView/ScrollView.windows.js +1959 -0
  8. package/Libraries/Components/View/View.windows.js +107 -56
  9. package/Libraries/Image/Image.windows.js +42 -21
  10. package/Libraries/Text/Text.d.ts +16 -1
  11. package/Microsoft.ReactNative/CompositionComponentView.idl +0 -5
  12. package/Microsoft.ReactNative/CompositionSwitcher.idl +4 -0
  13. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +32 -0
  14. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +159 -4
  15. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +11 -4
  16. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +0 -4
  17. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +22 -17
  18. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +1 -27
  19. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +0 -2
  20. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.cpp +36 -11
  21. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.h +3 -0
  22. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +50 -125
  23. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +9 -6
  24. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +31 -12
  25. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +6 -1
  26. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +2 -2
  27. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +145 -19
  28. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +13 -0
  29. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentDescriptor.h +0 -2
  30. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +134 -11
  31. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +6 -0
  32. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputEventEmitter.cpp +31 -0
  33. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputEventEmitter.h +14 -1
  34. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.cpp +6 -2
  35. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h +4 -1
  36. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +127 -109
  37. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.h +28 -25
  38. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.cpp +8 -18
  39. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.h +12 -35
  40. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +53 -11
  41. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +10 -2
  42. package/Microsoft.ReactNative/Fabric/ImageRequestParams.cpp +26 -0
  43. package/Microsoft.ReactNative/Fabric/WindowsImageManager.cpp +38 -8
  44. package/Microsoft.ReactNative/Fabric/WindowsImageManager.h +3 -1
  45. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +206 -41
  46. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h +14 -0
  47. package/Microsoft.ReactNative/Modules/Animated/AnimationDriver.cpp +2 -1
  48. package/Microsoft.ReactNative/ReactNativeIsland.idl +3 -0
  49. package/Microsoft.ReactNative/Utils/ImageUtils.h +1 -0
  50. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  51. package/PropertySheets/NuGet.LockFile.props +1 -1
  52. package/PropertySheets/WebView2.props +1 -1
  53. package/PropertySheets/WinUI.props +1 -1
  54. package/Shared/Networking/WinRTWebSocketResource.cpp +82 -96
  55. package/Shared/Networking/WinRTWebSocketResource.h +91 -7
  56. package/Shared/Shared.vcxitems +3 -1
  57. package/Shared/Shared.vcxitems.filters +1 -0
  58. package/package.json +1 -1
@@ -101,6 +101,7 @@ const View: React.AbstractComponent<
101
101
  }: ViewProps,
102
102
  forwardedRef,
103
103
  ) => {
104
+ const hasTextAncestor = React.useContext(TextAncestor);
104
105
  const _accessibilityLabelledBy =
105
106
  ariaLabelledBy?.split(/\s*,\s*/g) ?? accessibilityLabelledBy;
106
107
 
@@ -241,64 +242,114 @@ const View: React.AbstractComponent<
241
242
  );
242
243
  }
243
244
 
245
+ const actualView = (
246
+ <ViewNativeComponent
247
+ {...otherProps}
248
+ accessibilityLiveRegion={
249
+ ariaLive === 'off' ? 'none' : ariaLive ?? accessibilityLiveRegion
250
+ }
251
+ accessibilityLabel={ariaLabel ?? accessibilityLabel}
252
+ accessibilityLevel={ariaLevel ?? accessibilityLevel}
253
+ accessibilityPosInSet={ariaPosinset ?? accessibilityPosInSet}
254
+ accessibilitySetSize={ariaSetsize ?? accessibilitySetSize}
255
+ focusable={_focusable}
256
+ disabled={disabled}
257
+ accessibilityState={_accessibilityState}
258
+ accessibilityElementsHidden={ariaHidden ?? accessibilityElementsHidden}
259
+ accessibilityLabelledBy={_accessibilityLabelledBy}
260
+ accessibilityValue={_accessibilityValue}
261
+ importantForAccessibility={
262
+ ariaHidden === true
263
+ ? 'no-hide-descendants'
264
+ : importantForAccessibility
265
+ }
266
+ nativeID={id ?? nativeID}
267
+ ref={forwardedRef}
268
+ onKeyDown={_keyDown}
269
+ onKeyDownCapture={_keyDownCapture}
270
+ onKeyUp={_keyUp}
271
+ onKeyUpCapture={_keyUpCapture}
272
+ // [Windows
273
+ accessible={_accessible}
274
+ children={
275
+ importantForAccessibility === 'no-hide-descendants'
276
+ ? childrenWithImportantForAccessibility(otherProps.children)
277
+ : otherProps.children
278
+ }
279
+ // Windows]
280
+ />
281
+ );
282
+
283
+ // [Windows - Paper doesn't support Views in Text while Fabric does
284
+ if (global.RN$Bridgeless !== true) {
285
+ return (
286
+ // [Windows
287
+ // In core this is a TextAncestor.Provider value={false} See
288
+ // https://github.com/facebook/react-native/commit/66601e755fcad10698e61d20878d52194ad0e90c
289
+ // But since Views are not currently supported in Text, we do not need the extra provider
290
+ <TextAncestor.Consumer>
291
+ {hasTextAncestor => {
292
+ invariant(
293
+ !hasTextAncestor,
294
+ 'Nesting of <View> within <Text> is not currently supported.',
295
+ );
296
+ return (
297
+ <ViewNativeComponent
298
+ {...otherProps}
299
+ accessibilityLiveRegion={
300
+ ariaLive === 'off'
301
+ ? 'none'
302
+ : ariaLive ?? accessibilityLiveRegion
303
+ }
304
+ accessibilityLabel={ariaLabel ?? accessibilityLabel}
305
+ accessibilityLevel={ariaLevel ?? accessibilityLevel}
306
+ accessibilityPosInSet={ariaPosinset ?? accessibilityPosInSet}
307
+ accessibilitySetSize={ariaSetsize ?? accessibilitySetSize}
308
+ focusable={_focusable}
309
+ disabled={disabled}
310
+ accessibilityState={_accessibilityState}
311
+ accessibilityElementsHidden={
312
+ ariaHidden ?? accessibilityElementsHidden
313
+ }
314
+ accessibilityLabelledBy={_accessibilityLabelledBy}
315
+ accessibilityValue={_accessibilityValue}
316
+ importantForAccessibility={
317
+ ariaHidden === true
318
+ ? 'no-hide-descendants'
319
+ : importantForAccessibility
320
+ }
321
+ nativeID={id ?? nativeID}
322
+ ref={forwardedRef}
323
+ onKeyDown={_keyDown}
324
+ onKeyDownCapture={_keyDownCapture}
325
+ onKeyUp={_keyUp}
326
+ onKeyUpCapture={_keyUpCapture}
327
+ // [Windows
328
+ accessible={_accessible}
329
+ children={
330
+ importantForAccessibility === 'no-hide-descendants'
331
+ ? childrenWithImportantForAccessibility(otherProps.children)
332
+ : otherProps.children
333
+ }
334
+ // Windows]
335
+ />
336
+ );
337
+ }}
338
+ </TextAncestor.Consumer>
339
+ // Windows]
340
+ );
341
+ } else {
342
+ if (hasTextAncestor) {
343
+ return (
344
+ <TextAncestor.Provider value={false}>
345
+ {actualView}
346
+ </TextAncestor.Provider>
347
+ );
348
+ }
349
+ }
244
350
  // Windows]
245
351
 
246
- return (
247
- // [Windows
248
- // In core this is a TextAncestor.Provider value={false} See
249
- // https://github.com/facebook/react-native/commit/66601e755fcad10698e61d20878d52194ad0e90c
250
- // But since Views are not currently supported in Text, we do not need the extra provider
251
- <TextAncestor.Consumer>
252
- {hasTextAncestor => {
253
- invariant(
254
- !hasTextAncestor,
255
- 'Nesting of <View> within <Text> is not currently supported.',
256
- );
257
- return (
258
- <ViewNativeComponent
259
- {...otherProps}
260
- accessibilityLiveRegion={
261
- ariaLive === 'off'
262
- ? 'none'
263
- : ariaLive ?? accessibilityLiveRegion
264
- }
265
- accessibilityLabel={ariaLabel ?? accessibilityLabel}
266
- accessibilityLevel={ariaLevel ?? accessibilityLevel}
267
- accessibilityPosInSet={ariaPosinset ?? accessibilityPosInSet}
268
- accessibilitySetSize={ariaSetsize ?? accessibilitySetSize}
269
- focusable={_focusable}
270
- disabled={disabled}
271
- accessibilityState={_accessibilityState}
272
- accessibilityElementsHidden={
273
- ariaHidden ?? accessibilityElementsHidden
274
- }
275
- accessibilityLabelledBy={_accessibilityLabelledBy}
276
- accessibilityValue={_accessibilityValue}
277
- importantForAccessibility={
278
- ariaHidden === true
279
- ? 'no-hide-descendants'
280
- : importantForAccessibility
281
- }
282
- nativeID={id ?? nativeID}
283
- ref={forwardedRef}
284
- onKeyDown={_keyDown}
285
- onKeyDownCapture={_keyDownCapture}
286
- onKeyUp={_keyUp}
287
- onKeyUpCapture={_keyUpCapture}
288
- // [Windows
289
- accessible={_accessible}
290
- children={
291
- importantForAccessibility === 'no-hide-descendants'
292
- ? childrenWithImportantForAccessibility(otherProps.children)
293
- : otherProps.children
294
- }
295
- // Windows]
296
- />
297
- );
298
- }}
299
- </TextAncestor.Consumer>
300
- // Windows]
301
- );
352
+ return actualView;
302
353
  },
303
354
  );
304
355
 
@@ -28,6 +28,7 @@ import {convertObjectFitToResizeMode} from './ImageUtils';
28
28
  import ImageViewNativeComponent from './ImageViewNativeComponent';
29
29
  import NativeImageLoaderIOS from './NativeImageLoaderIOS';
30
30
  import resolveAssetSource from './resolveAssetSource';
31
+ import TextInlineImageNativeComponent from './TextInlineImageNativeComponent';
31
32
  import * as React from 'react';
32
33
 
33
34
  function getSize(
@@ -171,20 +172,20 @@ let BaseImage: AbstractImageIOS = React.forwardRef((props, forwardedRef) => {
171
172
 
172
173
  const actualRef = useWrapRefWithImageAttachedCallbacks(forwardedRef);
173
174
 
174
- return (
175
- // [Windows
176
- <TextAncestor.Consumer>
177
- {hasTextAncestor => {
178
- invariant(
179
- !hasTextAncestor,
180
- 'Nesting of <Image> within <Text> is not currently supported.',
181
- );
182
- // windows]
183
-
184
- return (
185
- <ImageAnalyticsTagContext.Consumer>
186
- {analyticTag => {
187
- return (
175
+ // [Windows - Paper doesn't support Views in Text while Fabric does
176
+ if (global.RN$Bridgeless !== true) {
177
+ return (
178
+ // [Windows
179
+ <TextAncestor.Consumer>
180
+ {hasTextAncestor => {
181
+ invariant(
182
+ !hasTextAncestor,
183
+ 'Nesting of <Image> within <Text> is not currently supported.',
184
+ );
185
+ // windows]
186
+ return (
187
+ <ImageAnalyticsTagContext.Consumer>
188
+ {analyticTag => (
188
189
  <ImageViewNativeComponent
189
190
  accessibilityState={_accessibilityState}
190
191
  {...restProps}
@@ -197,13 +198,33 @@ let BaseImage: AbstractImageIOS = React.forwardRef((props, forwardedRef) => {
197
198
  source={sources}
198
199
  internal_analyticTag={analyticTag}
199
200
  />
200
- );
201
- }}
202
- </ImageAnalyticsTagContext.Consumer>
203
- );
204
- }}
205
- </TextAncestor.Consumer>
206
- );
201
+ )}
202
+ </ImageAnalyticsTagContext.Consumer>
203
+ );
204
+ }}
205
+ </TextAncestor.Consumer>
206
+ );
207
+ } else {
208
+ return (
209
+ <ImageAnalyticsTagContext.Consumer>
210
+ {analyticTag => (
211
+ <ImageViewNativeComponent
212
+ accessibilityState={_accessibilityState}
213
+ {...restProps}
214
+ accessible={props.alt !== undefined ? true : props.accessible}
215
+ accessibilityLabel={accessibilityLabel ?? props.alt}
216
+ ref={actualRef}
217
+ style={style}
218
+ resizeMode={resizeMode}
219
+ tintColor={tintColor}
220
+ source={sources}
221
+ internal_analyticTag={analyticTag}
222
+ />
223
+ )}
224
+ </ImageAnalyticsTagContext.Consumer>
225
+ );
226
+ }
227
+ // Windows]
207
228
  });
208
229
 
209
230
  const imageComponentDecorator = unstable_getImageComponentDecorator();
@@ -12,7 +12,7 @@ import {Constructor} from '../../types/private/Utilities';
12
12
  import {AccessibilityProps} from '../Components/View/ViewAccessibility';
13
13
  import {NativeMethods} from '../../types/public/ReactNativeTypes';
14
14
  import {ColorValue, StyleProp} from '../StyleSheet/StyleSheet';
15
- import {TextStyle} from '../StyleSheet/StyleSheetTypes';
15
+ import {TextStyle, ViewStyle} from '../StyleSheet/StyleSheetTypes';
16
16
  import {
17
17
  GestureResponderEvent,
18
18
  LayoutChangeEvent,
@@ -101,10 +101,20 @@ export interface TextPropsAndroid {
101
101
  android_hyphenationFrequency?: 'normal' | 'none' | 'full' | undefined;
102
102
  }
103
103
 
104
+ export interface TextPropsWindows {
105
+ /**
106
+ * The tooltip to show when the text is clicked.
107
+ */
108
+ // [Windows
109
+ tooltip?: string | undefined;
110
+ // Windows]
111
+ }
112
+
104
113
  // https://reactnative.dev/docs/text#props
105
114
  export interface TextProps
106
115
  extends TextPropsIOS,
107
116
  TextPropsAndroid,
117
+ TextPropsWindows,
108
118
  AccessibilityProps {
109
119
  /**
110
120
  * Specifies whether fonts should scale to respect Text Size accessibility settings.
@@ -209,6 +219,11 @@ export interface TextProps
209
219
  * Specifies smallest possible scale a font can reach when adjustsFontSizeToFit is enabled. (values 0.01-1.0).
210
220
  */
211
221
  minimumFontScale?: number | undefined;
222
+
223
+ /**
224
+ * Controls how touch events are handled. Similar to `View`'s `pointerEvents`.
225
+ */
226
+ pointerEvents?: ViewStyle['pointerEvents'] | undefined;
212
227
  }
213
228
 
214
229
  /**
@@ -89,11 +89,6 @@ namespace Microsoft.ReactNative.Composition
89
89
  Microsoft.ReactNative.ViewProps ViewProps { get; };
90
90
  };
91
91
 
92
- // Some other interfaces we could consider implementing/exposing
93
- // Use ifdef USE_EXPERIMENTAL_WINUI3 to add these
94
- // Microsoft.UI.Content.IContentLink // Use ifdef USE_EXPERIMENTAL_WINUI3
95
- // Microsoft.UI.Content.IContentSiteBridge
96
- // Microsoft.UI.Content.IContentSiteBridge2 // Use ifdef USE_EXPERIMENTAL_WINUI3
97
92
  [experimental]
98
93
  [webhosthidden]
99
94
  runtimeclass ContentIslandComponentView : ViewComponentView {
@@ -109,11 +109,15 @@ namespace Microsoft.ReactNative.Composition.Experimental
109
109
  void Brush(IBrush brush);
110
110
  void ScrollEnabled(Boolean isScrollEnabled);
111
111
  event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollPositionChanged;
112
+ event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollBeginDrag;
112
113
  void ContentSize(Windows.Foundation.Numerics.Vector2 size);
113
114
  Windows.Foundation.Numerics.Vector3 ScrollPosition { get; };
114
115
  void ScrollBy(Windows.Foundation.Numerics.Vector3 offset, Boolean animate);
115
116
  void TryUpdatePosition(Windows.Foundation.Numerics.Vector3 position, Boolean animate);
116
117
  void OnPointerPressed(Microsoft.ReactNative.Composition.Input.PointerRoutedEventArgs args);
118
+ void SetDecelerationRate(Windows.Foundation.Numerics.Vector3 decelerationRate);
119
+ void SetMaximumZoomScale(Single maximumZoomScale);
120
+ void SetMinimumZoomScale(Single minimumZoomScale);
117
121
  Boolean Horizontal;
118
122
  }
119
123
 
@@ -708,6 +708,8 @@ struct CompScrollerVisual : winrt::implements<
708
708
  typename TTypeRedirects::InteractionTrackerInertiaStateEnteredArgs args) noexcept {
709
709
  m_outer->m_custom = false;
710
710
  m_outer->m_inertia = true;
711
+ m_outer->m_currentPosition = args.NaturalRestingPosition();
712
+ m_outer->FireScrollBeginDrag({args.NaturalRestingPosition().x, args.NaturalRestingPosition().y});
711
713
  }
712
714
  void InteractingStateEntered(
713
715
  typename TTypeRedirects::InteractionTracker sender,
@@ -834,6 +836,18 @@ struct CompScrollerVisual : winrt::implements<
834
836
  UpdateInteractionModes();
835
837
  }
836
838
 
839
+ void SetDecelerationRate(winrt::Windows::Foundation::Numerics::float3 const &decelerationRate) noexcept {
840
+ m_interactionTracker.PositionInertiaDecayRate(decelerationRate);
841
+ }
842
+
843
+ void SetMaximumZoomScale(float maximumZoomScale) const noexcept {
844
+ m_interactionTracker.MaxScale(maximumZoomScale);
845
+ }
846
+
847
+ void SetMinimumZoomScale(float minimumZoomScale) noexcept {
848
+ m_interactionTracker.MinScale(minimumZoomScale);
849
+ }
850
+
837
851
  void Opacity(float opacity) noexcept {
838
852
  m_visual.Opacity(opacity);
839
853
  }
@@ -918,10 +932,21 @@ struct CompScrollerVisual : winrt::implements<
918
932
  return m_scrollPositionChangedEvent.add(handler);
919
933
  }
920
934
 
935
+ winrt::event_token ScrollBeginDrag(
936
+ winrt::Windows::Foundation::EventHandler<
937
+ winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs> const
938
+ &handler) noexcept {
939
+ return m_scrollBeginDragEvent.add(handler);
940
+ }
941
+
921
942
  void ScrollPositionChanged(winrt::event_token const &token) noexcept {
922
943
  m_scrollPositionChangedEvent.remove(token);
923
944
  }
924
945
 
946
+ void ScrollBeginDrag(winrt::event_token const &token) noexcept {
947
+ m_scrollBeginDragEvent.remove(token);
948
+ }
949
+
925
950
  void ContentSize(winrt::Windows::Foundation::Numerics::float2 const &size) noexcept {
926
951
  m_contentSize = size;
927
952
  m_contentVisual.Size(size);
@@ -992,6 +1017,10 @@ struct CompScrollerVisual : winrt::implements<
992
1017
  m_scrollPositionChangedEvent(*this, winrt::make<CompScrollPositionChangedArgs>(position));
993
1018
  }
994
1019
 
1020
+ void FireScrollBeginDrag(winrt::Windows::Foundation::Numerics::float2 position) noexcept {
1021
+ m_scrollBeginDragEvent(*this, winrt::make<CompScrollPositionChangedArgs>(position));
1022
+ }
1023
+
995
1024
  void UpdateMaxPosition() noexcept {
996
1025
  m_interactionTracker.MaxPosition(
997
1026
  {std::max<float>(m_contentSize.x - m_visualSize.x, 0),
@@ -1010,6 +1039,9 @@ struct CompScrollerVisual : winrt::implements<
1010
1039
  winrt::event<winrt::Windows::Foundation::EventHandler<
1011
1040
  winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
1012
1041
  m_scrollPositionChangedEvent;
1042
+ winrt::event<winrt::Windows::Foundation::EventHandler<
1043
+ winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
1044
+ m_scrollBeginDragEvent;
1013
1045
  typename TTypeRedirects::SpriteVisual m_visual{nullptr};
1014
1046
  typename TTypeRedirects::SpriteVisual m_contentVisual{nullptr};
1015
1047
  typename TTypeRedirects::InteractionTracker m_interactionTracker{nullptr};
@@ -3,6 +3,7 @@
3
3
  #include <Fabric/ComponentView.h>
4
4
  #include <Fabric/Composition/CompositionTextRangeProvider.h>
5
5
  #include <Fabric/Composition/ParagraphComponentView.h>
6
+ #include <Fabric/Composition/ScrollViewComponentView.h>
6
7
  #include <Fabric/Composition/SwitchComponentView.h>
7
8
  #include <Fabric/Composition/TextInput/WindowsTextInputComponentView.h>
8
9
  #include <Unicode.h>
@@ -37,12 +38,10 @@ CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider(
37
38
  }
38
39
  }
39
40
 
40
- #ifdef USE_EXPERIMENTAL_WINUI3
41
41
  CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider(
42
42
  const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
43
43
  const winrt::Microsoft::UI::Content::ChildSiteLink &childSiteLink) noexcept
44
44
  : m_view{componentView}, m_childSiteLink{childSiteLink} {}
45
- #endif // USE_EXPERIMENTAL_WINUI3
46
45
 
47
46
  HRESULT __stdcall CompositionDynamicAutomationProvider::Navigate(
48
47
  NavigateDirection direction,
@@ -50,7 +49,6 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Navigate(
50
49
  if (pRetVal == nullptr)
51
50
  return E_POINTER;
52
51
 
53
- #ifdef USE_EXPERIMENTAL_WINUI3
54
52
  if (m_childSiteLink) {
55
53
  if (direction == NavigateDirection_FirstChild || direction == NavigateDirection_LastChild) {
56
54
  auto fragment = m_childSiteLink.AutomationProvider().try_as<IRawElementProviderFragment>();
@@ -58,7 +56,6 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Navigate(
58
56
  return S_OK;
59
57
  }
60
58
  }
61
- #endif // USE_EXPERIMENTAL_WINUI3
62
59
 
63
60
  return UiaNavigateHelper(m_view.view(), direction, *pRetVal);
64
61
  }
@@ -231,6 +228,12 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
231
228
  AddRef();
232
229
  }
233
230
 
231
+ if (patternId == UIA_ScrollPatternId &&
232
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>()) {
233
+ *pRetVal = static_cast<IScrollProvider *>(this);
234
+ AddRef();
235
+ }
236
+
234
237
  if (patternId == UIA_ValuePatternId &&
235
238
  ((strongView
236
239
  .try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() &&
@@ -341,6 +344,8 @@ long GetControlTypeFromString(const std::string &role) noexcept {
341
344
  return UIA_TreeControlTypeId;
342
345
  } else if (role == "treeitem") {
343
346
  return UIA_TreeItemControlTypeId;
347
+ } else if (role == "pane") {
348
+ return UIA_PaneControlTypeId;
344
349
  }
345
350
  assert(false);
346
351
  return UIA_GroupControlTypeId;
@@ -606,6 +611,156 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::ScrollIntoView() {
606
611
  return S_OK;
607
612
  }
608
613
 
614
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontalScrollPercent(double *pRetVal) {
615
+ BOOL horizontallyScrollable;
616
+ auto hr = get_HorizontallyScrollable(&horizontallyScrollable);
617
+ if (!SUCCEEDED(hr)) {
618
+ return hr;
619
+ }
620
+ if (!horizontallyScrollable) {
621
+ *pRetVal = UIA_ScrollPatternNoScroll;
622
+ } else {
623
+ auto strongView = m_view.view();
624
+ auto scrollComponentView =
625
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
626
+ *pRetVal = scrollComponentView->getScrollPositionX();
627
+ }
628
+ return S_OK;
629
+ }
630
+
631
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticalScrollPercent(double *pRetVal) {
632
+ BOOL verticallyScrollable;
633
+ auto hr = get_VerticallyScrollable(&verticallyScrollable);
634
+ if (!SUCCEEDED(hr)) {
635
+ return hr;
636
+ }
637
+ if (!verticallyScrollable) {
638
+ *pRetVal = UIA_ScrollPatternNoScroll;
639
+ } else {
640
+ auto strongView = m_view.view();
641
+ auto scrollComponentView =
642
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
643
+ *pRetVal = scrollComponentView->getScrollPositionY();
644
+ }
645
+ return S_OK;
646
+ }
647
+
648
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontalViewSize(double *pRetVal) {
649
+ BOOL horizontallyScrollable;
650
+ auto hr = get_HorizontallyScrollable(&horizontallyScrollable);
651
+ if (!SUCCEEDED(hr)) {
652
+ return hr;
653
+ }
654
+ if (!horizontallyScrollable) {
655
+ *pRetVal = 100;
656
+ } else {
657
+ auto strongView = m_view.view();
658
+ auto scrollComponentView =
659
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
660
+ *pRetVal = scrollComponentView->getHorizontalSize();
661
+ }
662
+ return S_OK;
663
+ }
664
+
665
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticalViewSize(double *pRetVal) {
666
+ BOOL verticallyScrollable;
667
+ auto hr = get_VerticallyScrollable(&verticallyScrollable);
668
+ if (!SUCCEEDED(hr)) {
669
+ return hr;
670
+ }
671
+ if (!verticallyScrollable) {
672
+ *pRetVal = 100;
673
+ } else {
674
+ auto strongView = m_view.view();
675
+ auto scrollComponentView =
676
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
677
+ *pRetVal = scrollComponentView->getVerticalSize();
678
+ }
679
+ return S_OK;
680
+ }
681
+
682
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontallyScrollable(BOOL *pRetVal) {
683
+ if (pRetVal == nullptr)
684
+ return E_POINTER;
685
+ auto strongView = m_view.view();
686
+
687
+ if (!strongView)
688
+ return UIA_E_ELEMENTNOTAVAILABLE;
689
+
690
+ auto props = std::static_pointer_cast<const facebook::react::ScrollViewProps>(
691
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
692
+ if (props == nullptr)
693
+ return UIA_E_ELEMENTNOTAVAILABLE;
694
+ *pRetVal = (props->horizontal && props->scrollEnabled);
695
+ return S_OK;
696
+ }
697
+
698
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticallyScrollable(BOOL *pRetVal) {
699
+ if (pRetVal == nullptr)
700
+ return E_POINTER;
701
+ auto strongView = m_view.view();
702
+
703
+ if (!strongView)
704
+ return UIA_E_ELEMENTNOTAVAILABLE;
705
+
706
+ auto props = std::static_pointer_cast<const facebook::react::ScrollViewProps>(
707
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
708
+ if (props == nullptr)
709
+ return UIA_E_ELEMENTNOTAVAILABLE;
710
+ *pRetVal = (!props->horizontal && props->scrollEnabled);
711
+ return S_OK;
712
+ }
713
+
714
+ HRESULT __stdcall CompositionDynamicAutomationProvider::Scroll(
715
+ ScrollAmount horizontalAmount,
716
+ ScrollAmount verticalAmount) {
717
+ DispatchAccessibilityAction(m_view, "scroll");
718
+ auto strongView = m_view.view();
719
+ auto scrollComponentView =
720
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
721
+ BOOL verticallyScrollable;
722
+ BOOL horizontallyScrollable;
723
+ float vertical = 0.0f;
724
+ float horizontal = 0.0f;
725
+ auto hr = get_VerticallyScrollable(&verticallyScrollable);
726
+ if (!SUCCEEDED(hr)) {
727
+ return hr;
728
+ }
729
+ if (verticallyScrollable) {
730
+ if (verticalAmount == ScrollAmount_LargeIncrement) {
731
+ scrollComponentView->pageDown(true);
732
+ } else if (verticalAmount == ScrollAmount_LargeDecrement) {
733
+ scrollComponentView->pageUp(true);
734
+ } else if (verticalAmount == ScrollAmount_SmallIncrement) {
735
+ scrollComponentView->lineDown(true);
736
+ } else if (verticalAmount == ScrollAmount_SmallDecrement) {
737
+ scrollComponentView->lineUp(true);
738
+ }
739
+ }
740
+ hr = get_HorizontallyScrollable(&horizontallyScrollable);
741
+ if (!SUCCEEDED(hr)) {
742
+ return hr;
743
+ }
744
+ if (horizontallyScrollable) {
745
+ if (horizontalAmount == ScrollAmount_LargeIncrement) {
746
+ scrollComponentView->pageDown(true);
747
+ } else if (horizontalAmount == ScrollAmount_LargeDecrement) {
748
+ scrollComponentView->pageUp(true);
749
+ } else if (horizontalAmount == ScrollAmount_SmallIncrement) {
750
+ scrollComponentView->lineRight(true);
751
+ } else if (horizontalAmount == ScrollAmount_SmallDecrement) {
752
+ scrollComponentView->lineLeft(true);
753
+ }
754
+ }
755
+ return S_OK;
756
+ }
757
+
758
+ HRESULT __stdcall CompositionDynamicAutomationProvider::SetScrollPercent(
759
+ double horiztonalPercent,
760
+ double verticalPercent) {
761
+ return S_OK;
762
+ }
763
+
609
764
  BSTR StringToBSTR(const std::string &str) {
610
765
  // Calculate the required BSTR size in bytes
611
766
  int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
@@ -15,6 +15,7 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
15
15
  IRawElementProviderSimple,
16
16
  IInvokeProvider,
17
17
  IScrollItemProvider,
18
+ IScrollProvider,
18
19
  IValueProvider,
19
20
  IRangeValueProvider,
20
21
  IToggleProvider,
@@ -25,11 +26,9 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
25
26
  CompositionDynamicAutomationProvider(
26
27
  const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView) noexcept;
27
28
 
28
- #ifdef USE_EXPERIMENTAL_WINUI3
29
29
  CompositionDynamicAutomationProvider(
30
30
  const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
31
31
  const winrt::Microsoft::UI::Content::ChildSiteLink &childContentLink) noexcept;
32
- #endif // USE_EXPERIMENTAL_WINUI3
33
32
 
34
33
  // inherited via IRawElementProviderFragment
35
34
  virtual HRESULT __stdcall Navigate(NavigateDirection direction, IRawElementProviderFragment **pRetVal) override;
@@ -52,6 +51,16 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
52
51
  // inherited via IScrollItemProvider
53
52
  HRESULT __stdcall ScrollIntoView() override;
54
53
 
54
+ // inherited via IScrollProvider
55
+ HRESULT __stdcall get_HorizontalScrollPercent(double *pRetVal) override;
56
+ HRESULT __stdcall get_VerticalScrollPercent(double *pRetVal) override;
57
+ HRESULT __stdcall get_HorizontalViewSize(double *pRetVal) override;
58
+ HRESULT __stdcall get_VerticalViewSize(double *pRetVal) override;
59
+ HRESULT __stdcall get_HorizontallyScrollable(BOOL *pRetVal) override;
60
+ HRESULT __stdcall get_VerticallyScrollable(BOOL *pRetVal) override;
61
+ HRESULT __stdcall Scroll(ScrollAmount horizontalAmount, ScrollAmount verticalAmount) override;
62
+ HRESULT __stdcall SetScrollPercent(double horiztonalPercent, double verticalPercent) override;
63
+
55
64
  // inherited via IValueProvider
56
65
  virtual HRESULT __stdcall SetValue(LPCWSTR val) override;
57
66
  virtual HRESULT __stdcall get_Value(BSTR *pRetVal) override;
@@ -93,10 +102,8 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
93
102
  ::Microsoft::ReactNative::ReactTaggedView m_view;
94
103
  winrt::com_ptr<ITextProvider2> m_textProvider;
95
104
  std::vector<winrt::com_ptr<IRawElementProviderSimple>> m_selectionItems;
96
- #ifdef USE_EXPERIMENTAL_WINUI3
97
105
  // Non-null when this UIA node is the peer of a ContentIslandComponentView.
98
106
  winrt::Microsoft::UI::Content::ChildSiteLink m_childSiteLink{nullptr};
99
- #endif
100
107
  };
101
108
 
102
109
  } // namespace winrt::Microsoft::ReactNative::implementation