react-native-windows 0.81.0-preview.1 → 0.81.0-preview.4

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.
@@ -1,178 +1,179 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT License.
3
3
 
4
- #include "NamespaceRedirect.h"
5
4
  #include "DocString.h"
5
+ #include "NamespaceRedirect.h"
6
6
  import "Composition.Input.idl";
7
7
 
8
- namespace Microsoft.ReactNative.Composition.Experimental
8
+ namespace Microsoft.ReactNative.Composition.Experimental {
9
+ enum CompositionStretch {
10
+ None,
11
+ Fill,
12
+ Uniform,
13
+ UniformToFill,
14
+ };
15
+
16
+ enum BackfaceVisibility { Inherit, Visible, Hidden };
17
+
18
+ enum AnimationClass {
19
+ None = 0,
20
+ ScrollBar,
21
+ ScrollBarThumbHorizontal,
22
+ ScrollBarThumbVertical,
23
+ SwitchThumb,
24
+ };
25
+
26
+ enum SnapPointsAlignment {
27
+ Near = 0, // Start alignment (left/top)
28
+ Center = 1, // Center alignment
29
+ Far = 2, // End alignment (right/bottom)
30
+ };
31
+
32
+ [webhosthidden][uuid("172def51-9e1a-4e3c-841a-e5a470065acc")] // uuid needed for empty interfaces
33
+ [version(0)][experimental] interface IBrush {}
34
+
35
+ [webhosthidden][experimental] interface IDrawingSurfaceBrush
36
+ requires IBrush
37
+ {
38
+ void HorizontalAlignmentRatio(Single value);
39
+ void VerticalAlignmentRatio(Single value);
40
+ void Stretch(CompositionStretch value);
41
+ }
42
+
43
+ [webhosthidden][experimental] interface IDropShadow {
44
+ void Offset(Windows.Foundation.Numerics.Vector3 value);
45
+ void Opacity(Single value);
46
+ void BlurRadius(Single value);
47
+ void Color(Windows.UI.Color value);
48
+ }
49
+
50
+ [webhosthidden][experimental] interface IVisual {
51
+ void InsertAt(IVisual visual, Int32 index);
52
+ void Remove(IVisual visual);
53
+ IVisual GetAt(UInt32 index);
54
+ void Opacity(Single opacity);
55
+ void Scale(Windows.Foundation.Numerics.Vector3 scale);
56
+ void TransformMatrix(Windows.Foundation.Numerics.Matrix4x4 transform);
57
+ void RotationAngle(Single angle);
58
+ void IsVisible(Boolean isVisible);
59
+ void Size(Windows.Foundation.Numerics.Vector2 size);
60
+ void Offset(Windows.Foundation.Numerics.Vector3 offset);
61
+ void Offset(Windows.Foundation.Numerics.Vector3 offset, Windows.Foundation.Numerics.Vector3 relativeAdjustment);
62
+ void RelativeSizeWithOffset(
63
+ Windows.Foundation.Numerics.Vector2 size, Windows.Foundation.Numerics.Vector2 relativeSizeAdjustment);
64
+ BackfaceVisibility BackfaceVisibility {
65
+ get;
66
+ set;
67
+ };
68
+ String Comment {
69
+ get;
70
+ set;
71
+ };
72
+ void AnimationClass(AnimationClass value);
73
+ }
74
+
75
+ [webhosthidden][experimental] interface ISpriteVisual
76
+ requires IVisual
77
+ {
78
+ void Brush(IBrush brush);
79
+ void Shadow(IDropShadow shadow);
80
+ }
81
+
82
+ [webhosthidden][experimental] interface IRoundedRectangleVisual
83
+ requires IVisual
9
84
  {
10
- enum CompositionStretch
11
- {
12
- None,
13
- Fill,
14
- Uniform,
15
- UniformToFill,
85
+ void Brush(IBrush brush);
86
+ void CornerRadius(Windows.Foundation.Numerics.Vector2 value);
87
+ void StrokeBrush(IBrush brush);
88
+ void StrokeThickness(Single value);
89
+ }
90
+
91
+ [webhosthidden][experimental] interface IScrollPositionChangedArgs {
92
+ Windows.Foundation.Numerics.Vector2 Position {
93
+ get;
16
94
  };
95
+ }
17
96
 
18
- enum BackfaceVisibility
19
- {
20
- Inherit,
21
- Visible,
22
- Hidden
97
+ [webhosthidden][experimental] interface IScrollVisual
98
+ requires IVisual
99
+ {
100
+ void Brush(IBrush brush);
101
+ void ScrollEnabled(Boolean isScrollEnabled);
102
+ event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollPositionChanged;
103
+ event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollBeginDrag;
104
+ event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollEndDrag;
105
+ event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollMomentumBegin;
106
+ event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollMomentumEnd;
107
+ void ContentSize(Windows.Foundation.Numerics.Vector2 size);
108
+ Windows.Foundation.Numerics.Vector3 ScrollPosition {
109
+ get;
110
+ };
111
+ void ScrollBy(Windows.Foundation.Numerics.Vector3 offset, Boolean animate);
112
+ void TryUpdatePosition(Windows.Foundation.Numerics.Vector3 position, Boolean animate);
113
+ void OnPointerPressed(Microsoft.ReactNative.Composition.Input.PointerRoutedEventArgs args);
114
+ void SetDecelerationRate(Windows.Foundation.Numerics.Vector3 decelerationRate);
115
+ void SetMaximumZoomScale(Single maximumZoomScale);
116
+ void SetMinimumZoomScale(Single minimumZoomScale);
117
+ Boolean Horizontal;
118
+ void SetSnapPoints(
119
+ Boolean snapToStart, Boolean snapToEnd, Windows.Foundation.Collections.IVectorView<Single> offsets);
120
+ void PagingEnabled(Boolean pagingEnabled);
121
+ void SnapToInterval(Single interval);
122
+ void SnapToAlignment(SnapPointsAlignment alignment);
123
+ }
124
+
125
+ [webhosthidden][experimental] interface IActivityVisual
126
+ requires IVisual
127
+ {
128
+ void Size(Single value);
129
+ void Brush(IBrush brush);
130
+ void StartAnimation();
131
+ void StopAnimation();
132
+ }
133
+
134
+ [webhosthidden][experimental] interface ICaretVisual {
135
+ IVisual InnerVisual {
136
+ get;
23
137
  };
24
-
25
- enum AnimationClass
26
- {
27
- None = 0,
28
- ScrollBar,
29
- ScrollBarThumbHorizontal,
30
- ScrollBarThumbVertical,
31
- SwitchThumb,
138
+ void Size(Windows.Foundation.Numerics.Vector2 size);
139
+ void Position(Windows.Foundation.Numerics.Vector2 position);
140
+ Boolean IsVisible {
141
+ get;
142
+ set;
32
143
  };
144
+ void Brush(IBrush brush);
145
+ }
33
146
 
34
- [webhosthidden]
35
- [uuid("172def51-9e1a-4e3c-841a-e5a470065acc")] // uuid needed for empty interfaces
36
- [version(0)]
37
- [experimental]
38
- interface IBrush {
39
- }
40
-
41
- [webhosthidden]
42
- [experimental]
43
- interface IDrawingSurfaceBrush requires IBrush
44
- {
45
- void HorizontalAlignmentRatio(Single value);
46
- void VerticalAlignmentRatio(Single value);
47
- void Stretch(CompositionStretch value);
48
- }
49
-
50
- [webhosthidden]
51
- [experimental]
52
- interface IDropShadow {
53
- void Offset(Windows.Foundation.Numerics.Vector3 value);
54
- void Opacity(Single value);
55
- void BlurRadius(Single value);
56
- void Color(Windows.UI.Color value);
57
- }
58
-
59
- [webhosthidden]
60
- [experimental]
61
- interface IVisual
62
- {
63
- void InsertAt(IVisual visual, Int32 index);
64
- void Remove(IVisual visual);
65
- IVisual GetAt(UInt32 index);
66
- void Opacity(Single opacity);
67
- void Scale(Windows.Foundation.Numerics.Vector3 scale);
68
- void TransformMatrix(Windows.Foundation.Numerics.Matrix4x4 transform);
69
- void RotationAngle(Single angle);
70
- void IsVisible(Boolean isVisible);
71
- void Size(Windows.Foundation.Numerics.Vector2 size);
72
- void Offset(Windows.Foundation.Numerics.Vector3 offset);
73
- void Offset(Windows.Foundation.Numerics.Vector3 offset, Windows.Foundation.Numerics.Vector3 relativeAdjustment);
74
- void RelativeSizeWithOffset(Windows.Foundation.Numerics.Vector2 size, Windows.Foundation.Numerics.Vector2 relativeSizeAdjustment);
75
- BackfaceVisibility BackfaceVisibility{ get; set; };
76
- String Comment { get; set; };
77
- void AnimationClass(AnimationClass value);
78
- }
79
-
80
- [webhosthidden]
81
- [experimental]
82
- interface ISpriteVisual requires IVisual
83
- {
84
- void Brush(IBrush brush);
85
- void Shadow(IDropShadow shadow);
86
- }
87
-
88
- [webhosthidden]
89
- [experimental]
90
- interface IRoundedRectangleVisual requires IVisual
91
- {
92
- void Brush(IBrush brush);
93
- void CornerRadius(Windows.Foundation.Numerics.Vector2 value);
94
- void StrokeBrush(IBrush brush);
95
- void StrokeThickness(Single value);
96
- }
97
-
98
- [webhosthidden]
99
- [experimental]
100
- interface IScrollPositionChangedArgs
101
- {
102
- Windows.Foundation.Numerics.Vector2 Position { get; };
103
- }
104
-
105
- [webhosthidden]
106
- [experimental]
107
- interface IScrollVisual requires IVisual
108
- {
109
- void Brush(IBrush brush);
110
- void ScrollEnabled(Boolean isScrollEnabled);
111
- event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollPositionChanged;
112
- event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollBeginDrag;
113
- event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollEndDrag;
114
- event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollMomentumBegin;
115
- event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollMomentumEnd;
116
- void ContentSize(Windows.Foundation.Numerics.Vector2 size);
117
- Windows.Foundation.Numerics.Vector3 ScrollPosition { get; };
118
- void ScrollBy(Windows.Foundation.Numerics.Vector3 offset, Boolean animate);
119
- void TryUpdatePosition(Windows.Foundation.Numerics.Vector3 position, Boolean animate);
120
- void OnPointerPressed(Microsoft.ReactNative.Composition.Input.PointerRoutedEventArgs args);
121
- void SetDecelerationRate(Windows.Foundation.Numerics.Vector3 decelerationRate);
122
- void SetMaximumZoomScale(Single maximumZoomScale);
123
- void SetMinimumZoomScale(Single minimumZoomScale);
124
- Boolean Horizontal;
125
- void SetSnapPoints(Boolean snapToStart, Boolean snapToEnd, Windows.Foundation.Collections.IVectorView<Single> offsets);
126
- }
127
-
128
- [webhosthidden]
129
- [experimental]
130
- interface IActivityVisual requires IVisual
131
- {
132
- void Size(Single value);
133
- void Brush(IBrush brush);
134
- void StartAnimation();
135
- void StopAnimation();
136
- }
137
-
138
- [webhosthidden]
139
- [experimental]
140
- interface ICaretVisual
141
- {
142
- IVisual InnerVisual { get; };
143
- void Size(Windows.Foundation.Numerics.Vector2 size);
144
- void Position(Windows.Foundation.Numerics.Vector2 position);
145
- Boolean IsVisible { get; set; };
146
- void Brush(IBrush brush);
147
- }
148
-
149
- [webhosthidden]
150
- [experimental]
151
- interface IFocusVisual
152
- {
153
- IVisual InnerVisual { get; };
154
- Boolean IsFocused { get; set; };
155
- Single ScaleFactor { get; set; };
156
- }
157
-
158
- [webhosthidden]
159
- [experimental]
160
- interface ICompositionContext
161
- {
162
- ISpriteVisual CreateSpriteVisual();
163
- IScrollVisual CreateScrollerVisual();
164
- IRoundedRectangleVisual CreateRoundedRectangleVisual();
165
- IActivityVisual CreateActivityVisual();
166
- ICaretVisual CreateCaretVisual();
167
- IFocusVisual CreateFocusVisual();
168
- IDropShadow CreateDropShadow();
169
- IBrush CreateColorBrush(Windows.UI.Color color);
170
- IDrawingSurfaceBrush CreateDrawingSurfaceBrush(Windows.Foundation.Size surfaceSize,
147
+ [webhosthidden][experimental] interface IFocusVisual {
148
+ IVisual InnerVisual {
149
+ get;
150
+ };
151
+ Boolean IsFocused {
152
+ get;
153
+ set;
154
+ };
155
+ Single ScaleFactor {
156
+ get;
157
+ set;
158
+ };
159
+ }
160
+
161
+ [webhosthidden][experimental] interface ICompositionContext {
162
+ ISpriteVisual CreateSpriteVisual();
163
+ IScrollVisual CreateScrollerVisual();
164
+ IRoundedRectangleVisual CreateRoundedRectangleVisual();
165
+ IActivityVisual CreateActivityVisual();
166
+ ICaretVisual CreateCaretVisual();
167
+ IFocusVisual CreateFocusVisual();
168
+ IDropShadow CreateDropShadow();
169
+ IBrush CreateColorBrush(Windows.UI.Color color);
170
+ IDrawingSurfaceBrush CreateDrawingSurfaceBrush(
171
+ Windows.Foundation.Size surfaceSize,
171
172
  Windows.Graphics.DirectX.DirectXPixelFormat pixelFormat,
172
173
  Windows.Graphics.DirectX.DirectXAlphaMode alphaMode);
173
174
 
174
- // TODO Add and hook up to rootnode - to notify the tree
175
- // event Windows.Foundation.EventHandler<RenderingDeviceReplacedArgs> RenderingDeviceReplaced;
176
- }
175
+ // TODO Add and hook up to rootnode - to notify the tree
176
+ // event Windows.Foundation.EventHandler<RenderingDeviceReplacedArgs> RenderingDeviceReplaced;
177
+ }
177
178
 
178
- } // namespace Microsoft.ReactNative.Composition.Experimental
179
+ } // namespace Microsoft.ReactNative.Composition. Experimental
@@ -910,6 +910,31 @@ struct CompScrollerVisual : winrt::implements<
910
910
  m_snapToOffsets.push_back(offset);
911
911
  }
912
912
  }
913
+ // Match Paper behavior: snapToOffsets disables pagingEnabled and snapToInterval
914
+ if (!m_snapToOffsets.empty()) {
915
+ m_pagingEnabled = false;
916
+ m_snapToInterval = 0.0f;
917
+ }
918
+ ConfigureSnapInertiaModifiers();
919
+ }
920
+
921
+ void PagingEnabled(bool pagingEnabled) noexcept {
922
+ m_pagingEnabled = pagingEnabled;
923
+ ConfigureSnapInertiaModifiers();
924
+ }
925
+
926
+ void SnapToInterval(float interval) noexcept {
927
+ m_snapToInterval = interval;
928
+ // Match Paper behavior: snapToOffsets disables snapToInterval
929
+ if (!m_snapToOffsets.empty()) {
930
+ m_snapToInterval = 0.0f;
931
+ }
932
+ ConfigureSnapInertiaModifiers();
933
+ }
934
+
935
+ void SnapToAlignment(
936
+ winrt::Microsoft::ReactNative::Composition::Experimental::SnapPointsAlignment alignment) noexcept {
937
+ m_snapToAlignment = alignment;
913
938
  ConfigureSnapInertiaModifiers();
914
939
  }
915
940
 
@@ -934,9 +959,13 @@ struct CompScrollerVisual : winrt::implements<
934
959
  }
935
960
 
936
961
  void Size(winrt::Windows::Foundation::Numerics::float2 const &size) noexcept {
962
+ bool sizeChanged = (m_visualSize.x != size.x || m_visualSize.y != size.y);
937
963
  m_visualSize = size;
938
964
  m_visual.Size(size);
939
965
  UpdateMaxPosition();
966
+ if (sizeChanged && m_pagingEnabled) {
967
+ ConfigureSnapInertiaModifiers();
968
+ }
940
969
  }
941
970
 
942
971
  void Offset(winrt::Windows::Foundation::Numerics::float3 const &offset) noexcept {
@@ -1046,9 +1075,13 @@ struct CompScrollerVisual : winrt::implements<
1046
1075
  }
1047
1076
 
1048
1077
  void ContentSize(winrt::Windows::Foundation::Numerics::float2 const &size) noexcept {
1078
+ bool sizeChanged = (m_contentSize.x != size.x || m_contentSize.y != size.y);
1049
1079
  m_contentSize = size;
1050
1080
  m_contentVisual.Size(size);
1051
1081
  UpdateMaxPosition();
1082
+ if (sizeChanged && m_pagingEnabled) {
1083
+ ConfigureSnapInertiaModifiers();
1084
+ }
1052
1085
  }
1053
1086
 
1054
1087
  winrt::Windows::Foundation::Numerics::float3 ScrollPosition() const noexcept {
@@ -1155,11 +1188,73 @@ struct CompScrollerVisual : winrt::implements<
1155
1188
  // Collect and deduplicate all snap positions
1156
1189
  std::vector<float> snapPositions;
1157
1190
 
1158
- if (m_snapToStart) {
1159
- snapPositions.push_back(0.0f);
1191
+ // Priority: snapToOffsets > snapToInterval > pagingEnabled
1192
+ if (!m_snapToOffsets.empty()) {
1193
+ // Use explicit snap points when snapToOffsets is set (highest priority)
1194
+ if (m_snapToStart) {
1195
+ snapPositions.push_back(0.0f);
1196
+ }
1197
+ snapPositions.insert(snapPositions.end(), m_snapToOffsets.begin(), m_snapToOffsets.end());
1198
+ } else if (m_snapToInterval > 0.0f) {
1199
+ // Generate snap points at interval positions
1200
+ float viewportSize = m_horizontal ? visualSize.x : visualSize.y;
1201
+ float maxScroll =
1202
+ m_horizontal ? std::max(contentSize.x - visualSize.x, 0.0f) : std::max(contentSize.y - visualSize.y, 0.0f);
1203
+
1204
+ // Calculate alignment offset based on snapToAlignment
1205
+ float alignmentOffset = 0.0f;
1206
+ using SnapPointsAlignment = winrt::Microsoft::ReactNative::Composition::Experimental::SnapPointsAlignment;
1207
+ if (m_snapToAlignment == SnapPointsAlignment::Center) {
1208
+ alignmentOffset = -viewportSize / 2.0f;
1209
+ } else if (m_snapToAlignment == SnapPointsAlignment::Far) {
1210
+ alignmentOffset = -viewportSize;
1211
+ }
1212
+ // Near (start) alignment has no offset (alignmentOffset = 0)
1213
+
1214
+ // Generate snap points at interval positions with alignment offset
1215
+ for (float position = alignmentOffset; position <= maxScroll; position += m_snapToInterval) {
1216
+ if (position >= 0.0f) { // Only include positions >= 0
1217
+ snapPositions.push_back(position);
1218
+ }
1219
+ }
1220
+
1221
+ // Ensure we have at least the start position
1222
+ if (snapPositions.empty() || snapPositions.front() > 0.0f) {
1223
+ snapPositions.insert(snapPositions.begin(), 0.0f);
1224
+ }
1225
+
1226
+ // Ensure the end position is included if not already
1227
+ if (!snapPositions.empty() && snapPositions.back() < maxScroll) {
1228
+ snapPositions.push_back(maxScroll);
1229
+ }
1230
+ } else if (m_pagingEnabled) {
1231
+ // Generate snap points at viewport intervals (paging)
1232
+ float viewportSize = m_horizontal ? visualSize.x : visualSize.y;
1233
+ float maxScroll =
1234
+ m_horizontal ? std::max(contentSize.x - visualSize.x, 0.0f) : std::max(contentSize.y - visualSize.y, 0.0f);
1235
+
1236
+ // Only generate paging snap points if viewport size is valid
1237
+ if (viewportSize > 0 && maxScroll > 0) {
1238
+ // Add snap points at each page (viewport size) interval
1239
+ for (float position = 0.0f; position <= maxScroll; position += viewportSize) {
1240
+ snapPositions.push_back(position);
1241
+ }
1242
+
1243
+ // Ensure the end position is included if not already
1244
+ if (!snapPositions.empty() && snapPositions.back() < maxScroll) {
1245
+ snapPositions.push_back(maxScroll);
1246
+ }
1247
+ } else {
1248
+ // If content fits in viewport or invalid size, just snap to start
1249
+ snapPositions.push_back(0.0f);
1250
+ }
1251
+ } else {
1252
+ // No interval or paging - use explicit snap points only
1253
+ if (m_snapToStart) {
1254
+ snapPositions.push_back(0.0f);
1255
+ }
1160
1256
  }
1161
1257
 
1162
- snapPositions.insert(snapPositions.end(), m_snapToOffsets.begin(), m_snapToOffsets.end());
1163
1258
  std::sort(snapPositions.begin(), snapPositions.end());
1164
1259
  snapPositions.erase(std::unique(snapPositions.begin(), snapPositions.end()), snapPositions.end());
1165
1260
 
@@ -1222,7 +1317,8 @@ struct CompScrollerVisual : winrt::implements<
1222
1317
  restingValues.push_back(restingValue);
1223
1318
  }
1224
1319
 
1225
- if (m_snapToEnd) {
1320
+ // Only add snapToEnd handling when NOT using pagingEnabled or snapToInterval (they already include end position)
1321
+ if (m_snapToEnd && !m_pagingEnabled && m_snapToInterval <= 0.0f) {
1226
1322
  auto endRestingValue = TTypeRedirects::InteractionTrackerInertiaRestingValue::Create(compositor);
1227
1323
 
1228
1324
  // Create property sets to dynamically compute content - visual size
@@ -1286,6 +1382,10 @@ struct CompScrollerVisual : winrt::implements<
1286
1382
  bool m_horizontal{false};
1287
1383
  bool m_snapToStart{true};
1288
1384
  bool m_snapToEnd{true};
1385
+ bool m_pagingEnabled{false};
1386
+ float m_snapToInterval{0.0f};
1387
+ winrt::Microsoft::ReactNative::Composition::Experimental::SnapPointsAlignment m_snapToAlignment{
1388
+ winrt::Microsoft::ReactNative::Composition::Experimental::SnapPointsAlignment::Near};
1289
1389
  std::vector<float> m_snapToOffsets;
1290
1390
  bool m_inertia{false};
1291
1391
  bool m_custom{false};
@@ -35,26 +35,38 @@ struct ModalHostState
35
35
  struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::Foundation::IInspectable>,
36
36
  ::Microsoft::ReactNativeSpecs::BaseModalHostView<ModalHostView> {
37
37
  ~ModalHostView() {
38
- if (m_reactNativeIsland) {
39
- m_reactNativeIsland.Island().Close();
40
- }
38
+ if (m_popUp) {
39
+ // Unregister closing event handler
40
+ if (m_appWindow && m_appWindowClosingToken) {
41
+ m_appWindow.Closing(m_appWindowClosingToken);
42
+ m_appWindowClosingToken.value = 0;
43
+ }
41
44
 
42
- // Add AppWindow closing token cleanup
43
- if (m_appWindow && m_appWindowClosingToken) {
44
- m_appWindow.Closing(m_appWindowClosingToken);
45
- m_appWindowClosingToken.value = 0;
46
- }
45
+ // Reset topWindowID before destroying
46
+ if (m_prevWindowID) {
47
+ winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
48
+ m_reactContext.Properties().Handle(), m_prevWindowID);
49
+ m_prevWindowID = 0;
50
+ }
47
51
 
48
- if (m_popUp) {
49
- if (m_departFocusToken && !m_popUp.IsClosed()) {
50
- // WASDK BUG: InputFocusNavigationHost::GetForSiteBridge fails on a DesktopPopupSiteBridge
51
- // https://github.com/microsoft/react-native-windows/issues/14604
52
- /*
53
- auto navHost =
54
- winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteBridge(m_popUp.as<winrt::Microsoft::UI::Content::IContentSiteBridge>());
55
- navHost.DepartFocusRequested(m_departFocusToken);
56
- */
52
+ // Close island
53
+ if (m_reactNativeIsland) {
54
+ m_reactNativeIsland.Island().Close();
55
+ m_reactNativeIsland = nullptr;
56
+ }
57
+
58
+ // Hide popup
59
+ if (m_popUp.IsVisible()) {
60
+ m_popUp.Hide();
61
+ }
62
+
63
+ // Destroy AppWindow this automatically resumes parent window to receive inputs
64
+ if (m_appWindow) {
65
+ m_appWindow.Destroy();
66
+ m_appWindow = nullptr;
57
67
  }
68
+
69
+ // Close bridge
58
70
  m_popUp.Close();
59
71
  m_popUp = nullptr;
60
72
  }
@@ -88,7 +100,7 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
88
100
  QueueShow(view);
89
101
  } else {
90
102
  m_visible = false;
91
- CloseWindow();
103
+ HideWindow();
92
104
  }
93
105
  }
94
106
 
@@ -219,31 +231,27 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
219
231
  }
220
232
  }
221
233
 
222
- void CloseWindow() noexcept {
223
- // enable input to parent before closing the modal window, so focus can return back to the parent window
224
- EnableWindow(m_parentHwnd, true);
234
+ /*
235
+ HideWindow called on visible=false
236
+ unmounts the modal window using onDismiss event
237
+ */
238
+ void HideWindow() noexcept {
239
+ // Hide popup
225
240
  if (m_popUp) {
226
241
  m_popUp.Hide();
227
242
  }
228
243
 
229
- // Unregister closing event handler
230
- if (m_appWindow && m_appWindowClosingToken) {
231
- m_appWindow.Closing(m_appWindowClosingToken);
232
- m_appWindowClosingToken.value = 0;
244
+ // Restore message routing to parent
245
+ if (m_prevWindowID) {
246
+ winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
247
+ m_reactContext.Properties().Handle(), m_prevWindowID);
233
248
  }
234
249
 
235
- // dispatch onDismiss event
250
+ // Dispatch onDismiss event
236
251
  if (auto eventEmitter = EventEmitter()) {
237
252
  ::Microsoft::ReactNativeSpecs::ModalHostViewEventEmitter::OnDismiss eventArgs;
238
253
  eventEmitter->onDismiss(eventArgs);
239
254
  }
240
-
241
- // reset the topWindowID
242
- if (m_prevWindowID) {
243
- winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
244
- m_reactContext.Properties().Handle(), m_prevWindowID);
245
- m_prevWindowID = 0;
246
- }
247
255
  }
248
256
 
249
257
  // creates a new modal window
@@ -814,6 +814,25 @@ void ScrollViewComponentView::updateProps(
814
814
  }
815
815
  m_scrollVisual.SetSnapPoints(newViewProps.snapToStart, newViewProps.snapToEnd, snapToOffsets.GetView());
816
816
  }
817
+
818
+ if (!oldProps || oldViewProps.pagingEnabled != newViewProps.pagingEnabled) {
819
+ m_scrollVisual.PagingEnabled(newViewProps.pagingEnabled);
820
+ }
821
+
822
+ if (!oldProps || oldViewProps.snapToInterval != newViewProps.snapToInterval) {
823
+ m_scrollVisual.SnapToInterval(static_cast<float>(newViewProps.snapToInterval));
824
+ }
825
+
826
+ if (!oldProps || oldViewProps.snapToAlignment != newViewProps.snapToAlignment) {
827
+ using SnapPointsAlignment = winrt::Microsoft::ReactNative::Composition::Experimental::SnapPointsAlignment;
828
+ SnapPointsAlignment alignment = SnapPointsAlignment::Near; // default is "start"
829
+ if (newViewProps.snapToAlignment == facebook::react::ScrollViewSnapToAlignment::Center) {
830
+ alignment = SnapPointsAlignment::Center;
831
+ } else if (newViewProps.snapToAlignment == facebook::react::ScrollViewSnapToAlignment::End) {
832
+ alignment = SnapPointsAlignment::Far;
833
+ }
834
+ m_scrollVisual.SnapToAlignment(alignment);
835
+ }
817
836
  }
818
837
 
819
838
  void ScrollViewComponentView::updateState(
@@ -697,10 +697,17 @@ void WindowsTextInputComponentView::OnPointerPressed(
697
697
  }
698
698
 
699
699
  if (m_textServices && msg) {
700
- LRESULT lresult;
701
- DrawBlock db(*this);
702
- auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
703
- args.Handled(hr != S_FALSE);
700
+ if (msg == WM_RBUTTONUP && !windowsTextInputProps().contextMenuHidden) {
701
+ ShowContextMenu(position);
702
+ args.Handled(true);
703
+ } else if (msg == WM_RBUTTONUP && windowsTextInputProps().contextMenuHidden) {
704
+ args.Handled(true);
705
+ } else {
706
+ LRESULT lresult;
707
+ DrawBlock db(*this);
708
+ auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
709
+ args.Handled(hr != S_FALSE);
710
+ }
704
711
  }
705
712
 
706
713
  // Emits the OnPressIn event
@@ -844,8 +851,8 @@ void WindowsTextInputComponentView::OnPointerWheelChanged(
844
851
  }
845
852
  void WindowsTextInputComponentView::OnKeyDown(
846
853
  const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept {
847
- // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with WinUI
848
- // behavior We do forward Ctrl+Tab to the textinput.
854
+ // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with
855
+ // WinUI behavior We do forward Ctrl+Tab to the textinput.
849
856
  if (args.Key() != winrt::Windows::System::VirtualKey::Tab ||
850
857
  (args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::Control) &
851
858
  winrt::Microsoft::UI::Input::VirtualKeyStates::Down) == winrt::Microsoft::UI::Input::VirtualKeyStates::Down) {
@@ -872,8 +879,8 @@ void WindowsTextInputComponentView::OnKeyDown(
872
879
 
873
880
  void WindowsTextInputComponentView::OnKeyUp(
874
881
  const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept {
875
- // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with WinUI
876
- // behavior We do forward Ctrl+Tab to the textinput.
882
+ // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with
883
+ // WinUI behavior We do forward Ctrl+Tab to the textinput.
877
884
  if (args.Key() != winrt::Windows::System::VirtualKey::Tab ||
878
885
  (args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::Control) &
879
886
  winrt::Microsoft::UI::Input::VirtualKeyStates::Down) == winrt::Microsoft::UI::Input::VirtualKeyStates::Down) {
@@ -943,8 +950,8 @@ bool WindowsTextInputComponentView::ShouldSubmit(
943
950
 
944
951
  void WindowsTextInputComponentView::OnCharacterReceived(
945
952
  const winrt::Microsoft::ReactNative::Composition::Input::CharacterReceivedRoutedEventArgs &args) noexcept {
946
- // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with WinUI
947
- // behavior We do forward Ctrl+Tab to the textinput.
953
+ // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with
954
+ // WinUI behavior We do forward Ctrl+Tab to the textinput.
948
955
  if ((args.KeyCode() == '\t') &&
949
956
  ((args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::Control) &
950
957
  winrt::Microsoft::UI::Input::VirtualKeyStates::Down) != winrt::Microsoft::UI::Input::VirtualKeyStates::Down)) {
@@ -1547,25 +1554,59 @@ void WindowsTextInputComponentView::UpdateParaFormat() noexcept {
1547
1554
  m_pf.dwMask = PFM_ALL;
1548
1555
 
1549
1556
  auto &textAlign = windowsTextInputProps().textAlign;
1557
+ auto &baseWritingDirection = windowsTextInputProps().textAttributes.baseWritingDirection;
1558
+
1559
+ // Handle writingDirection (baseWritingDirection)
1560
+ // For WritingDirection::Natural, use the computed layout direction from the layout tree
1561
+ // since direction can be overridden at any point in the tree
1562
+ bool isRTL = false;
1563
+ if (baseWritingDirection.has_value()) {
1564
+ if (*baseWritingDirection == facebook::react::WritingDirection::RightToLeft) {
1565
+ isRTL = true;
1566
+ m_pf.dwMask |= PFM_RTLPARA;
1567
+ m_pf.wEffects |= PFE_RTLPARA;
1568
+ } else if (*baseWritingDirection == facebook::react::WritingDirection::LeftToRight) {
1569
+ isRTL = false;
1570
+ // Ensure RTL flag is not set
1571
+ m_pf.wEffects &= ~PFE_RTLPARA;
1572
+ } else if (*baseWritingDirection == facebook::react::WritingDirection::Natural) {
1573
+ // Natural uses the layout direction computed from the tree
1574
+ isRTL = (layoutMetrics().layoutDirection == facebook::react::LayoutDirection::RightToLeft);
1575
+ if (isRTL) {
1576
+ m_pf.dwMask |= PFM_RTLPARA;
1577
+ m_pf.wEffects |= PFE_RTLPARA;
1578
+ } else {
1579
+ m_pf.wEffects &= ~PFE_RTLPARA;
1580
+ }
1581
+ }
1582
+ } else {
1583
+ // No explicit writing direction set - use layout direction from tree
1584
+ isRTL = (layoutMetrics().layoutDirection == facebook::react::LayoutDirection::RightToLeft);
1585
+ if (isRTL) {
1586
+ m_pf.dwMask |= PFM_RTLPARA;
1587
+ m_pf.wEffects |= PFE_RTLPARA;
1588
+ } else {
1589
+ m_pf.wEffects &= ~PFE_RTLPARA;
1590
+ }
1591
+ }
1550
1592
 
1593
+ // Handle textAlign
1551
1594
  if (textAlign == facebook::react::TextAlignment::Center) {
1552
1595
  m_pf.wAlignment = PFA_CENTER;
1553
1596
  } else if (textAlign == facebook::react::TextAlignment::Right) {
1554
1597
  m_pf.wAlignment = PFA_RIGHT;
1598
+ } else if (textAlign == facebook::react::TextAlignment::Justified) {
1599
+ m_pf.wAlignment = PFA_JUSTIFY;
1600
+ } else if (textAlign == facebook::react::TextAlignment::Natural) {
1601
+ // Natural alignment respects writing direction
1602
+ m_pf.wAlignment = isRTL ? PFA_RIGHT : PFA_LEFT;
1555
1603
  } else {
1604
+ // Default to left alignment
1556
1605
  m_pf.wAlignment = PFA_LEFT;
1557
1606
  }
1558
1607
 
1559
1608
  m_pf.cTabCount = 1;
1560
1609
  m_pf.rgxTabs[0] = lDefaultTab;
1561
-
1562
- /*
1563
- if (m_spcontroller->IsCurrentReadingOrderRTL())
1564
- {
1565
- m_pf.dwMask |= PFM_RTLPARA;
1566
- m_pf.wEffects |= PFE_RTLPARA;
1567
- }
1568
- */
1569
1610
  }
1570
1611
 
1571
1612
  void WindowsTextInputComponentView::OnRenderingDeviceLost() noexcept {
@@ -1826,4 +1867,47 @@ void WindowsTextInputComponentView::updateSpellCheck(bool enable) noexcept {
1826
1867
  winrt::check_hresult(
1827
1868
  m_textServices->TxSendMessage(EM_SETLANGOPTIONS, IMF_SPELLCHECKING, enable ? newLangOptions : 0, &lresult));
1828
1869
  }
1870
+
1871
+ void WindowsTextInputComponentView::ShowContextMenu(const winrt::Windows::Foundation::Point &position) noexcept {
1872
+ HMENU menu = CreatePopupMenu();
1873
+ if (!menu)
1874
+ return;
1875
+
1876
+ CHARRANGE selection;
1877
+ LRESULT res;
1878
+ m_textServices->TxSendMessage(EM_EXGETSEL, 0, reinterpret_cast<LPARAM>(&selection), &res);
1879
+
1880
+ bool hasSelection = selection.cpMin != selection.cpMax;
1881
+ bool isEmpty = GetTextFromRichEdit().empty();
1882
+ bool isReadOnly = windowsTextInputProps().editable == false;
1883
+ bool canPaste = !isReadOnly && IsClipboardFormatAvailable(CF_UNICODETEXT);
1884
+
1885
+ AppendMenuW(menu, MF_STRING | (hasSelection && !isReadOnly ? 0 : MF_GRAYED), 1, L"Cut");
1886
+ AppendMenuW(menu, MF_STRING | (hasSelection ? 0 : MF_GRAYED), 2, L"Copy");
1887
+ AppendMenuW(menu, MF_STRING | (canPaste ? 0 : MF_GRAYED), 3, L"Paste");
1888
+ AppendMenuW(menu, MF_STRING | (!isEmpty && !isReadOnly ? 0 : MF_GRAYED), 4, L"Select All");
1889
+
1890
+ POINT cursorPos;
1891
+ GetCursorPos(&cursorPos);
1892
+
1893
+ HWND hwnd = GetActiveWindow();
1894
+
1895
+ int cmd = TrackPopupMenu(
1896
+ menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY, cursorPos.x, cursorPos.y, 0, hwnd, NULL);
1897
+
1898
+ if (cmd == 1) { // Cut
1899
+ m_textServices->TxSendMessage(WM_CUT, 0, 0, &res);
1900
+ OnTextUpdated();
1901
+ } else if (cmd == 2) { // Copy
1902
+ m_textServices->TxSendMessage(WM_COPY, 0, 0, &res);
1903
+ } else if (cmd == 3) { // Paste
1904
+ m_textServices->TxSendMessage(WM_PASTE, 0, 0, &res);
1905
+ OnTextUpdated();
1906
+ } else if (cmd == 4) { // Select All
1907
+ m_textServices->TxSendMessage(EM_SETSEL, 0, -1, &res);
1908
+ }
1909
+
1910
+ DestroyMenu(menu);
1911
+ }
1912
+
1829
1913
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -118,6 +118,7 @@ struct WindowsTextInputComponentView
118
118
  void updateLetterSpacing(float letterSpacing) noexcept;
119
119
  void updateAutoCorrect(bool value) noexcept;
120
120
  void updateSpellCheck(bool value) noexcept;
121
+ void ShowContextMenu(const winrt::Windows::Foundation::Point &position) noexcept;
121
122
 
122
123
  winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{nullptr};
123
124
  winrt::Microsoft::ReactNative::Composition::Experimental::ICaretVisual m_caretVisual{nullptr};
@@ -136,6 +136,25 @@ void WindowsTextLayoutManager::GetTextLayout(
136
136
  outerFragment.textAttributes.lineHeight * 0.8f));
137
137
  }
138
138
 
139
+ // Set reading direction (RTL/LTR) based on baseWritingDirection
140
+ // Only set reading direction if explicitly specified to avoid breaking existing layouts
141
+ bool isRTL = false;
142
+ if (outerFragment.textAttributes.baseWritingDirection.has_value()) {
143
+ DWRITE_READING_DIRECTION readingDirection = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
144
+ if (*outerFragment.textAttributes.baseWritingDirection == facebook::react::WritingDirection::RightToLeft) {
145
+ readingDirection = DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;
146
+ isRTL = true;
147
+ } else if (*outerFragment.textAttributes.baseWritingDirection == facebook::react::WritingDirection::LeftToRight) {
148
+ readingDirection = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
149
+ isRTL = false;
150
+ } else if (*outerFragment.textAttributes.baseWritingDirection == facebook::react::WritingDirection::Natural) {
151
+ // Natural uses the layout direction from textAttributes
152
+ isRTL = (outerFragment.textAttributes.layoutDirection == facebook::react::LayoutDirection::RightToLeft);
153
+ readingDirection = isRTL ? DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
154
+ }
155
+ winrt::check_hresult(spTextFormat->SetReadingDirection(readingDirection));
156
+ }
157
+
139
158
  // Set text alignment
140
159
  DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
141
160
  if (outerFragment.textAttributes.alignment) {
@@ -152,9 +171,9 @@ void WindowsTextLayoutManager::GetTextLayout(
152
171
  case facebook::react::TextAlignment::Right:
153
172
  alignment = DWRITE_TEXT_ALIGNMENT_TRAILING;
154
173
  break;
155
- // TODO use LTR values
156
174
  case facebook::react::TextAlignment::Natural:
157
- alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
175
+ // Natural alignment respects reading direction if baseWritingDirection was set
176
+ alignment = isRTL ? DWRITE_TEXT_ALIGNMENT_TRAILING : DWRITE_TEXT_ALIGNMENT_LEADING;
158
177
  break;
159
178
  default:
160
179
  assert(false);
@@ -326,10 +326,32 @@ class ReactInspectorHostTargetDelegate : public jsinspector_modern::HostTargetDe
326
326
  ReactInspectorHostTargetDelegate(Mso::WeakPtr<ReactHost> &&reactHost) noexcept : m_reactHost(std::move(reactHost)) {}
327
327
 
328
328
  jsinspector_modern::HostTargetMetadata getMetadata() override {
329
- // TODO: (vmoroz) provide more info
330
- return {
331
- .integrationName = "React Native Windows (Host)",
332
- };
329
+ jsinspector_modern::HostTargetMetadata metadata{};
330
+ metadata.integrationName = "React Native Windows (Host)";
331
+ metadata.platform = "windows";
332
+
333
+ if (Mso::CntPtr<ReactHost> reactHost = m_reactHost.GetStrongPtr()) {
334
+ const ReactOptions &options = reactHost->Options();
335
+ if (!options.Identity.empty()) {
336
+ std::string identity = options.Identity;
337
+ // Replace illegal characters with underscore
338
+ for (char &c : identity) {
339
+ if (c == '\\' || c == '/' || c == ':' || c == '*' || c == '?' || c == '"' || c == '<' || c == '>' ||
340
+ c == '|') {
341
+ c = '_';
342
+ }
343
+ }
344
+ metadata.appDisplayName = identity;
345
+ }
346
+ }
347
+
348
+ wchar_t computerName[MAX_COMPUTERNAME_LENGTH + 1];
349
+ DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
350
+ if (GetComputerNameW(computerName, &size)) {
351
+ metadata.deviceName = winrt::to_string(computerName);
352
+ }
353
+
354
+ return metadata;
333
355
  }
334
356
 
335
357
  void onReload(jsinspector_modern::HostTargetDelegate::PageReloadRequest const &request) override {
@@ -630,9 +652,20 @@ void ReactHost::AddInspectorPage() noexcept {
630
652
  jsinspector_modern::InspectorTargetCapabilities capabilities;
631
653
  capabilities.nativePageReloads = true;
632
654
  capabilities.prefersFuseboxFrontend = true;
633
- // TODO: (vmoroz) improve the page name
655
+
656
+ auto metadata = m_inspectorHostTargetDelegate->getMetadata();
657
+ std::string pageName;
658
+ if (metadata.appDisplayName.has_value() && !metadata.appDisplayName.value().empty()) {
659
+ pageName = metadata.appDisplayName.value();
660
+ } else {
661
+ pageName = "React Native Windows (Experimental)";
662
+ }
663
+ if (metadata.deviceName.has_value() && !metadata.deviceName.value().empty()) {
664
+ pageName += " (" + metadata.deviceName.value() + ")";
665
+ }
666
+
634
667
  inspectorPageId = jsinspector_modern::getInspectorInstance().addPage(
635
- "React Native Windows (Experimental)",
668
+ pageName,
636
669
  "Hermes",
637
670
  [weakInspectorHostTarget =
638
671
  std::weak_ptr(m_inspectorHostTarget)](std::unique_ptr<jsinspector_modern::IRemoteConnection> remote)
@@ -10,11 +10,11 @@
10
10
  -->
11
11
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
12
12
  <PropertyGroup>
13
- <ReactNativeWindowsVersion>0.81.0-preview.1</ReactNativeWindowsVersion>
13
+ <ReactNativeWindowsVersion>0.81.0-preview.4</ReactNativeWindowsVersion>
14
14
  <ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
15
15
  <ReactNativeWindowsMinor>81</ReactNativeWindowsMinor>
16
16
  <ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
17
17
  <ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
18
- <ReactNativeWindowsCommitId>c90943314678ce91d624ceba523e50f8d35a5ea5</ReactNativeWindowsCommitId>
18
+ <ReactNativeWindowsCommitId>a999c767d29d998a9b7792f8dd1b28242f1395dc</ReactNativeWindowsCommitId>
19
19
  </PropertyGroup>
20
20
  </Project>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-windows",
3
- "version": "0.81.0-preview.1",
3
+ "version": "0.81.0-preview.4",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -2,8 +2,6 @@ const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const exclusionList = require('metro-config/src/defaults/exclusionList');
6
-
7
5
  const rnwPath = fs.realpathSync(
8
6
  path.resolve(require.resolve('react-native-windows/package.json'), '..'),
9
7
  );
@@ -25,7 +23,7 @@ const config = {
25
23
  watchFolders: [rnwPath, rnwRootNodeModules, rnwPackages],
26
24
  // devMode]{{/devMode}}
27
25
  resolver: {
28
- blockList: exclusionList([
26
+ blockList: [
29
27
  // This stops "npx @react-native-community/cli run-windows" from causing the metro server to crash if its already running
30
28
  new RegExp(
31
29
  `${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`,
@@ -34,7 +32,7 @@ const config = {
34
32
  new RegExp(`${rnwPath}/build/.*`),
35
33
  new RegExp(`${rnwPath}/target/.*`),
36
34
  /.*\.ProjectImports\.zip/,
37
- ]),
35
+ ],
38
36
  //{{#devMode}} [devMode
39
37
  extraNodeModules: {
40
38
  'react-native-windows': rnwPath,
@@ -2,8 +2,6 @@ const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const exclusionList = require('metro-config/src/defaults/exclusionList');
6
-
7
5
  const rnwPath = fs.realpathSync(
8
6
  path.resolve(require.resolve('react-native-windows/package.json'), '..'),
9
7
  );
@@ -25,7 +23,7 @@ const config = {
25
23
  watchFolders: [rnwPath, rnwRootNodeModules, rnwPackages],
26
24
  // devMode]{{/devMode}}
27
25
  resolver: {
28
- blockList: exclusionList([
26
+ blockList: [
29
27
  // This stops "npx @react-native-community/cli run-windows" from causing the metro server to crash if its already running
30
28
  new RegExp(
31
29
  `${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`,
@@ -34,7 +32,7 @@ const config = {
34
32
  new RegExp(`${rnwPath}/build/.*`),
35
33
  new RegExp(`${rnwPath}/target/.*`),
36
34
  /.*\.ProjectImports\.zip/,
37
- ]),
35
+ ],
38
36
  //{{#devMode}} [devMode
39
37
  extraNodeModules: {
40
38
  'react-native-windows': rnwPath,
@@ -2,7 +2,6 @@ const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
4
  const escape = require('escape-string-regexp');
5
- const exclusionList = require('metro-config/src/defaults/exclusionList');
6
5
  const pack = require('../package.json');
7
6
 
8
7
  const root = path.resolve(__dirname, '..');
@@ -33,7 +32,7 @@ const config = {
33
32
  // We need to make sure that only one version is loaded for peerDependencies
34
33
  // So we block them at the root, and alias them to the versions in example's node_modules
35
34
  resolver: {
36
- blockList: exclusionList(
35
+ blockList:
37
36
  modules.map(
38
37
  (m) =>
39
38
  new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)
@@ -47,7 +46,7 @@ const config = {
47
46
  new RegExp(`${rnwPath}/target/.*`),
48
47
  /.*\.ProjectImports\.zip/,
49
48
  ])
50
- ),
49
+ ,
51
50
 
52
51
  extraNodeModules: modules.reduce((acc, name) => {
53
52
  acc[name] = path.join(__dirname, 'node_modules', name);