react-native-windows 0.83.0-preview.0 → 0.83.0-preview.2

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.
@@ -43,6 +43,14 @@ namespace Microsoft.ReactNative
43
43
  Last,
44
44
  };
45
45
 
46
+ enum FocusState
47
+ {
48
+ Unfocused = 0,
49
+ Pointer,
50
+ Keyboard,
51
+ Programmatic,
52
+ };
53
+
46
54
  [webhosthidden]
47
55
  [experimental]
48
56
  interface IComponentState
@@ -99,7 +107,7 @@ namespace Microsoft.ReactNative
99
107
  LayoutMetrics LayoutMetrics { get; };
100
108
  IInspectable UserData;
101
109
 
102
- Boolean TryFocus();
110
+ Boolean TryFocus(FocusState focusState);
103
111
 
104
112
  DOC_STRING("Used to handle key down events when this component is focused, or if a child component did not handle the key down")
105
113
  event Windows.Foundation.EventHandler<Microsoft.ReactNative.Composition.Input.KeyRoutedEventArgs> KeyDown;
@@ -283,6 +283,7 @@ void ComponentView::parent(const winrt::Microsoft::ReactNative::ComponentView &p
283
283
  oldRootView->TrySetFocusedComponent(
284
284
  oldParent,
285
285
  winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
286
+ winrt::Microsoft::ReactNative::FocusState::Programmatic,
286
287
  true /*forceNoSelectionIfCannotMove*/);
287
288
  }
288
289
  }
@@ -431,9 +432,10 @@ void ComponentView::GotFocus(winrt::event_token const &token) noexcept {
431
432
  m_gotFocusEvent.remove(token);
432
433
  }
433
434
 
434
- bool ComponentView::TryFocus() noexcept {
435
+ bool ComponentView::TryFocus(winrt::Microsoft::ReactNative::FocusState focusState) noexcept {
435
436
  if (auto root = rootComponentView()) {
436
- return root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
437
+ return root->TrySetFocusedComponent(
438
+ *get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None, focusState);
437
439
  }
438
440
 
439
441
  return false;
@@ -201,7 +201,7 @@ struct ComponentView
201
201
 
202
202
  LayoutMetrics LayoutMetrics() const noexcept;
203
203
 
204
- bool TryFocus() noexcept;
204
+ bool TryFocus(winrt::Microsoft::ReactNative::FocusState focusState) noexcept;
205
205
 
206
206
  virtual bool focusable() const noexcept;
207
207
  virtual facebook::react::SharedViewEventEmitter eventEmitterAtPoint(facebook::react::Point pt) noexcept;
@@ -608,6 +608,8 @@ int64_t CompositionEventHandler::SendMessage(HWND hwnd, uint32_t msg, uint64_t w
608
608
 
609
609
  void CompositionEventHandler::onKeyDown(
610
610
  const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept {
611
+ RootComponentView().UseKeyboardForProgrammaticFocus(true);
612
+
611
613
  if (auto focusedComponent = RootComponentView().GetFocusedComponent()) {
612
614
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(focusedComponent)->OnKeyDown(args);
613
615
 
@@ -631,7 +633,7 @@ void CompositionEventHandler::onKeyDown(
631
633
  }
632
634
 
633
635
  if (!fCtrl && args.Key() == winrt::Windows::System::VirtualKey::Tab) {
634
- if (RootComponentView().TryMoveFocus(!fShift)) {
636
+ if (RootComponentView().TryMoveFocus(!fShift, winrt::Microsoft::ReactNative::FocusState::Keyboard)) {
635
637
  args.Handled(true);
636
638
  }
637
639
 
@@ -641,6 +643,8 @@ void CompositionEventHandler::onKeyDown(
641
643
 
642
644
  void CompositionEventHandler::onKeyUp(
643
645
  const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept {
646
+ RootComponentView().UseKeyboardForProgrammaticFocus(true);
647
+
644
648
  if (auto focusedComponent = RootComponentView().GetFocusedComponent()) {
645
649
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(focusedComponent)->OnKeyUp(args);
646
650
 
@@ -1173,6 +1177,8 @@ void CompositionEventHandler::onPointerPressed(
1173
1177
  winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept {
1174
1178
  namespace Composition = winrt::Microsoft::ReactNative::Composition;
1175
1179
 
1180
+ RootComponentView().UseKeyboardForProgrammaticFocus(false);
1181
+
1176
1182
  // Clears any active text selection when left pointer is pressed
1177
1183
  if (pointerPoint.Properties().PointerUpdateKind() != Composition::Input::PointerUpdateKind::RightButtonPressed) {
1178
1184
  RootComponentView().ClearCurrentTextSelection();
@@ -1210,6 +1216,30 @@ void CompositionEventHandler::onPointerPressed(
1210
1216
  ActiveTouch activeTouch{0};
1211
1217
  activeTouch.touchType = UITouchType::Mouse;
1212
1218
 
1219
+ // Map PointerUpdateKind to W3C button value
1220
+ // https://developer.mozilla.org/docs/Web/API/MouseEvent/button
1221
+ auto updateKind = pointerPoint.Properties().PointerUpdateKind();
1222
+ switch (updateKind) {
1223
+ case Composition::Input::PointerUpdateKind::LeftButtonPressed:
1224
+ activeTouch.button = 0;
1225
+ break;
1226
+ case Composition::Input::PointerUpdateKind::MiddleButtonPressed:
1227
+ activeTouch.button = 1;
1228
+ break;
1229
+ case Composition::Input::PointerUpdateKind::RightButtonPressed:
1230
+ activeTouch.button = 2;
1231
+ break;
1232
+ case Composition::Input::PointerUpdateKind::XButton1Pressed:
1233
+ activeTouch.button = 3;
1234
+ break;
1235
+ case Composition::Input::PointerUpdateKind::XButton2Pressed:
1236
+ activeTouch.button = 4;
1237
+ break;
1238
+ default:
1239
+ activeTouch.button = -1;
1240
+ break;
1241
+ }
1242
+
1213
1243
  while (targetComponentView) {
1214
1244
  if (auto eventEmitter =
1215
1245
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(targetComponentView)
@@ -1245,6 +1275,8 @@ void CompositionEventHandler::onPointerReleased(
1245
1275
  winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept {
1246
1276
  int pointerId = pointerPoint.PointerId();
1247
1277
 
1278
+ RootComponentView().UseKeyboardForProgrammaticFocus(false);
1279
+
1248
1280
  auto activeTouch = std::find_if(m_activeTouches.begin(), m_activeTouches.end(), [pointerId](const auto &pair) {
1249
1281
  return pair.second.touch.identifier == pointerId;
1250
1282
  });
@@ -1394,8 +1426,34 @@ facebook::react::PointerEvent CompositionEventHandler::CreatePointerEventFromAct
1394
1426
 
1395
1427
  event.detail = 0;
1396
1428
 
1397
- // event.button = activeTouch.button;
1398
- // event.buttons = ButtonMaskToButtons(activeTouch.buttonMask);
1429
+ event.button = activeTouch.button;
1430
+
1431
+ // Build W3C buttons bitmask from the active button
1432
+ // https://developer.mozilla.org/docs/Web/API/MouseEvent/buttons
1433
+ if (IsEndishEventType(eventType)) {
1434
+ event.buttons = 0;
1435
+ } else {
1436
+ switch (activeTouch.button) {
1437
+ case 0:
1438
+ event.buttons = 1;
1439
+ break; // primary
1440
+ case 1:
1441
+ event.buttons = 4;
1442
+ break; // auxiliary (middle)
1443
+ case 2:
1444
+ event.buttons = 2;
1445
+ break; // secondary (right)
1446
+ case 3:
1447
+ event.buttons = 8;
1448
+ break; // X1
1449
+ case 4:
1450
+ event.buttons = 16;
1451
+ break; // X2
1452
+ default:
1453
+ event.buttons = 0;
1454
+ break;
1455
+ }
1456
+ }
1399
1457
 
1400
1458
  // UpdatePointerEventModifierFlags(event, activeTouch.modifierFlags);
1401
1459
 
@@ -373,7 +373,8 @@ void ComponentView::onGotFocus(
373
373
  const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
374
374
  if (args.OriginalSource() == Tag()) {
375
375
  m_eventEmitter->onFocus();
376
- if (viewProps()->enableFocusRing) {
376
+ if (viewProps()->enableFocusRing &&
377
+ rootComponentView()->focusState() == winrt::Microsoft::ReactNative::FocusState::Keyboard) {
377
378
  facebook::react::Rect focusRect = m_layoutMetrics.frame;
378
379
  focusRect.origin.x -= (FOCUS_VISUAL_WIDTH * 2);
379
380
  focusRect.origin.y -= (FOCUS_VISUAL_WIDTH * 2);
@@ -426,15 +427,20 @@ void ComponentView::HandleCommand(const winrt::Microsoft::ReactNative::HandleCom
426
427
  auto commandName = args.CommandName();
427
428
  if (commandName == L"focus") {
428
429
  if (auto root = rootComponentView()) {
429
- root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
430
+ root->TrySetFocusedComponent(
431
+ *get_strong(),
432
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
433
+ winrt::Microsoft::ReactNative::FocusState::Programmatic);
430
434
  }
431
435
  return;
432
436
  }
433
437
  if (commandName == L"blur") {
434
438
  if (auto root = rootComponentView()) {
435
439
  root->TrySetFocusedComponent(
436
- nullptr, winrt::Microsoft::ReactNative::FocusNavigationDirection::None); // Todo store this component as
437
- // previously focused element
440
+ nullptr,
441
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
442
+ winrt::Microsoft::ReactNative::FocusState::Programmatic); // Todo store this component as
443
+ // previously focused element
438
444
  }
439
445
  return;
440
446
  }
@@ -82,7 +82,7 @@ void ContentIslandComponentView::ConnectInternal() noexcept {
82
82
  m_navigationHost.DepartFocusRequested([wkThis = get_weak()](const auto &, const auto &args) {
83
83
  if (auto strongThis = wkThis.get()) {
84
84
  const bool next = (args.Request().Reason() != winrt::Microsoft::UI::Input::FocusNavigationReason::Last);
85
- strongThis->rootComponentView()->TryMoveFocus(next);
85
+ strongThis->rootComponentView()->TryMoveFocus(next, winrt::Microsoft::ReactNative::FocusState::Programmatic);
86
86
  args.Result(winrt::Microsoft::UI::Input::FocusNavigationResult::Moved);
87
87
  }
88
88
  });
@@ -622,7 +622,10 @@ void ParagraphComponentView::OnPointerPressed(
622
622
 
623
623
  // Focuses so we receive onLostFocus when clicking elsewhere
624
624
  if (auto root = rootComponentView()) {
625
- root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
625
+ root->TrySetFocusedComponent(
626
+ *get_strong(),
627
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
628
+ winrt::Microsoft::ReactNative::FocusState::Pointer);
626
629
  }
627
630
 
628
631
  args.Handled(true);
@@ -82,7 +82,8 @@ winrt::Microsoft::ReactNative::ComponentView RootComponentView::GetFocusedCompon
82
82
 
83
83
  void RootComponentView::SetFocusedComponent(
84
84
  const winrt::Microsoft::ReactNative::ComponentView &value,
85
- winrt::Microsoft::ReactNative::FocusNavigationDirection direction) noexcept {
85
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
86
+ winrt::Microsoft::ReactNative::FocusState focusState) noexcept {
86
87
  if (m_focusedComponent == value)
87
88
  return;
88
89
 
@@ -97,11 +98,26 @@ void RootComponentView::SetFocusedComponent(
97
98
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(rootView)->TrySetFocus();
98
99
  }
99
100
  m_focusedComponent = value;
101
+ if (focusState == winrt::Microsoft::ReactNative::FocusState::Programmatic) {
102
+ focusState =
103
+ (!m_useKeyboardForProgrammaticFocus || m_focusState == winrt::Microsoft::ReactNative::FocusState::Pointer)
104
+ ? winrt::Microsoft::ReactNative::FocusState::Pointer
105
+ : winrt::Microsoft::ReactNative::FocusState::Keyboard;
106
+ }
107
+ m_focusState = focusState;
100
108
  auto args = winrt::make<winrt::Microsoft::ReactNative::implementation::GotFocusEventArgs>(value, direction);
101
109
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(value)->onGotFocus(args);
102
110
  }
103
111
  }
104
112
 
113
+ winrt::Microsoft::ReactNative::FocusState RootComponentView::focusState() const noexcept {
114
+ return m_focusState;
115
+ }
116
+
117
+ void RootComponentView::UseKeyboardForProgrammaticFocus(bool value) noexcept {
118
+ m_useKeyboardForProgrammaticFocus = value;
119
+ }
120
+
105
121
  bool RootComponentView::NavigateFocus(const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept {
106
122
  if (request.Reason() == winrt::Microsoft::ReactNative::FocusNavigationReason::Restore) {
107
123
  if (m_focusedComponent)
@@ -116,7 +132,8 @@ bool RootComponentView::NavigateFocus(const winrt::Microsoft::ReactNative::Focus
116
132
  view,
117
133
  request.Reason() == winrt::Microsoft::ReactNative::FocusNavigationReason::First
118
134
  ? winrt::Microsoft::ReactNative::FocusNavigationDirection::First
119
- : winrt::Microsoft::ReactNative::FocusNavigationDirection::Last);
135
+ : winrt::Microsoft::ReactNative::FocusNavigationDirection::Last,
136
+ winrt::Microsoft::ReactNative::FocusState::Programmatic);
120
137
  }
121
138
  return view != nullptr;
122
139
  }
@@ -124,6 +141,7 @@ bool RootComponentView::NavigateFocus(const winrt::Microsoft::ReactNative::Focus
124
141
  bool RootComponentView::TrySetFocusedComponent(
125
142
  const winrt::Microsoft::ReactNative::ComponentView &view,
126
143
  winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
144
+ winrt::Microsoft::ReactNative::FocusState focusState,
127
145
  bool forceNoSelectionIfCannotMove /*= false*/) noexcept {
128
146
  auto target = view;
129
147
  auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
@@ -157,15 +175,15 @@ bool RootComponentView::TrySetFocusedComponent(
157
175
 
158
176
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(losingFocusArgs.NewFocusedComponent())
159
177
  ->rootComponentView()
160
- ->SetFocusedComponent(gettingFocusArgs.NewFocusedComponent(), direction);
178
+ ->SetFocusedComponent(gettingFocusArgs.NewFocusedComponent(), direction, focusState);
161
179
  } else {
162
- SetFocusedComponent(nullptr, direction);
180
+ SetFocusedComponent(nullptr, direction, focusState);
163
181
  }
164
182
 
165
183
  return true;
166
184
  }
167
185
 
168
- bool RootComponentView::TryMoveFocus(bool next) noexcept {
186
+ bool RootComponentView::TryMoveFocus(bool next, winrt::Microsoft::ReactNative::FocusState focusState) noexcept {
169
187
  if (!m_focusedComponent) {
170
188
  return NavigateFocus(winrt::Microsoft::ReactNative::FocusNavigationRequest(
171
189
  next ? winrt::Microsoft::ReactNative::FocusNavigationReason::First
@@ -173,7 +191,8 @@ bool RootComponentView::TryMoveFocus(bool next) noexcept {
173
191
  }
174
192
 
175
193
  Mso::Functor<bool(const winrt::Microsoft::ReactNative::ComponentView &)> fn =
176
- [currentlyFocused = m_focusedComponent, next](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
194
+ [currentlyFocused = m_focusedComponent, next, focusState](
195
+ const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
177
196
  if (view == currentlyFocused)
178
197
  return false;
179
198
  auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view);
@@ -185,7 +204,8 @@ bool RootComponentView::TryMoveFocus(bool next) noexcept {
185
204
  ->TrySetFocusedComponent(
186
205
  view,
187
206
  next ? winrt::Microsoft::ReactNative::FocusNavigationDirection::Next
188
- : winrt::Microsoft::ReactNative::FocusNavigationDirection::Previous);
207
+ : winrt::Microsoft::ReactNative::FocusNavigationDirection::Previous,
208
+ focusState);
189
209
  };
190
210
 
191
211
  if (winrt::Microsoft::ReactNative::implementation::walkTree(m_focusedComponent, next, fn)) {
@@ -249,7 +269,10 @@ void RootComponentView::start(const winrt::Microsoft::ReactNative::ReactNativeIs
249
269
  }
250
270
 
251
271
  void RootComponentView::stop() noexcept {
252
- SetFocusedComponent(nullptr, winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
272
+ SetFocusedComponent(
273
+ nullptr,
274
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
275
+ winrt::Microsoft::ReactNative::FocusState::Programmatic);
253
276
  if (m_visualAddedToIsland) {
254
277
  if (auto rootView = m_wkRootView.get()) {
255
278
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(rootView)->RemoveRenderedVisual(
@@ -30,15 +30,17 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
30
30
  winrt::Microsoft::ReactNative::ComponentView GetFocusedComponent() noexcept;
31
31
  void SetFocusedComponent(
32
32
  const winrt::Microsoft::ReactNative::ComponentView &value,
33
- winrt::Microsoft::ReactNative::FocusNavigationDirection direction) noexcept;
33
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
34
+ winrt::Microsoft::ReactNative::FocusState focusState) noexcept;
34
35
  bool TrySetFocusedComponent(
35
36
  const winrt::Microsoft::ReactNative::ComponentView &view,
36
37
  winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
38
+ winrt::Microsoft::ReactNative::FocusState focusState,
37
39
  bool forceNoSelectionIfCannotMove = false) noexcept;
38
40
 
39
41
  bool NavigateFocus(const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept;
40
42
 
41
- bool TryMoveFocus(bool next) noexcept;
43
+ bool TryMoveFocus(bool next, winrt::Microsoft::ReactNative::FocusState focusState) noexcept;
42
44
 
43
45
  RootComponentView *rootComponentView() const noexcept override;
44
46
 
@@ -90,14 +92,20 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
90
92
  void ClearCurrentTextSelection() noexcept;
91
93
  void SetViewWithTextSelection(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept;
92
94
 
95
+ winrt::Microsoft::ReactNative::FocusState focusState() const noexcept;
96
+
97
+ void UseKeyboardForProgrammaticFocus(bool value) noexcept;
98
+
93
99
  private:
94
100
  // should this be a ReactTaggedView? - It shouldn't actually matter since if the view is going away it should always
95
101
  // be clearing its focus But being a reactTaggedView might make it easier to identify cases where that isn't
96
102
  // happening.
97
103
  winrt::Microsoft::ReactNative::ComponentView m_focusedComponent{nullptr};
104
+ winrt::Microsoft::ReactNative::FocusState m_focusState{winrt::Microsoft::ReactNative::FocusState::Unfocused};
98
105
  winrt::weak_ref<winrt::Microsoft::ReactNative::ReactNativeIsland> m_wkRootView{nullptr};
99
106
  winrt::weak_ref<winrt::Microsoft::ReactNative::Composition::PortalComponentView> m_wkPortal{nullptr};
100
107
  bool m_visualAddedToIsland{false};
108
+ bool m_useKeyboardForProgrammaticFocus{true};
101
109
 
102
110
  ::Microsoft::ReactNative::ReactTaggedView m_viewWithTextSelection{
103
111
  winrt::Microsoft::ReactNative::ComponentView{nullptr}};
@@ -271,7 +271,10 @@ void SwitchComponentView::OnPointerPressed(
271
271
  m_supressAnimationForNextFrame = true;
272
272
 
273
273
  if (auto root = rootComponentView()) {
274
- root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
274
+ root->TrySetFocusedComponent(
275
+ *get_strong(),
276
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
277
+ winrt::Microsoft::ReactNative::FocusState::Pointer);
275
278
  }
276
279
 
277
280
  updateVisuals();
@@ -233,7 +233,9 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
233
233
  winrt::check_hresult(
234
234
  m_outer->QueryInterface(winrt::guid_of<winrt::Microsoft::ReactNative::ComponentView>(), winrt::put_abi(view)));
235
235
  m_outer->rootComponentView()->TrySetFocusedComponent(
236
- view, winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
236
+ view,
237
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
238
+ winrt::Microsoft::ReactNative::FocusState::Programmatic);
237
239
  // assert(false);
238
240
  // TODO focus
239
241
  }
@@ -1469,7 +1471,10 @@ void WindowsTextInputComponentView::onMounted() noexcept {
1469
1471
  // Handle autoFocus property - focus the component when mounted if autoFocus is true
1470
1472
  if (windowsTextInputProps().autoFocus) {
1471
1473
  if (auto root = rootComponentView()) {
1472
- root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
1474
+ root->TrySetFocusedComponent(
1475
+ *get_strong(),
1476
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
1477
+ winrt::Microsoft::ReactNative::FocusState::Programmatic);
1473
1478
  }
1474
1479
  }
1475
1480
  }
@@ -141,7 +141,10 @@ HRESULT UiaSetFocusHelper(::Microsoft::ReactNative::ReactTaggedView &view) noexc
141
141
  if (rootCV == nullptr)
142
142
  return UIA_E_ELEMENTNOTAVAILABLE;
143
143
 
144
- return rootCV->TrySetFocusedComponent(strongView, winrt::Microsoft::ReactNative::FocusNavigationDirection::None)
144
+ return rootCV->TrySetFocusedComponent(
145
+ strongView,
146
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
147
+ winrt::Microsoft::ReactNative::FocusState::Programmatic)
145
148
  ? S_OK
146
149
  : E_FAIL;
147
150
  }
@@ -266,6 +266,10 @@ class ReactNativeWindowsFeatureFlags : public facebook::react::ReactNativeFeatur
266
266
  return true;
267
267
  }
268
268
 
269
+ bool enableImperativeFocus() override {
270
+ return true;
271
+ }
272
+
269
273
  bool fuseboxEnabledRelease() override {
270
274
  return true; // Enable Fusebox (modern CDP backend) by default for React Native Windows
271
275
  }
@@ -10,11 +10,11 @@
10
10
  -->
11
11
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
12
12
  <PropertyGroup>
13
- <ReactNativeWindowsVersion>0.0.0-canary.1037</ReactNativeWindowsVersion>
13
+ <ReactNativeWindowsVersion>0.83.0-preview.2</ReactNativeWindowsVersion>
14
14
  <ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
15
- <ReactNativeWindowsMinor>0</ReactNativeWindowsMinor>
15
+ <ReactNativeWindowsMinor>83</ReactNativeWindowsMinor>
16
16
  <ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
17
- <ReactNativeWindowsCanary>true</ReactNativeWindowsCanary>
18
- <ReactNativeWindowsCommitId>d02a7c64b3d3528e4a0f622702921ba63bbeeb01</ReactNativeWindowsCommitId>
17
+ <ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
18
+ <ReactNativeWindowsCommitId>d89154d68c6b2f5f1a2355042d166f9dac8f1ba3</ReactNativeWindowsCommitId>
19
19
  </PropertyGroup>
20
20
  </Project>
@@ -0,0 +1,664 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #include "BaseViewProps.h"
9
+
10
+ #include <algorithm>
11
+
12
+ #include <react/featureflags/ReactNativeFeatureFlags.h>
13
+ #include <react/renderer/components/view/BackgroundImagePropsConversions.h>
14
+ #include <react/renderer/components/view/BoxShadowPropsConversions.h>
15
+ #include <react/renderer/components/view/FilterPropsConversions.h>
16
+ #include <react/renderer/components/view/conversions.h>
17
+ #include <react/renderer/components/view/primitives.h>
18
+ #include <react/renderer/components/view/propsConversions.h>
19
+ #include <react/renderer/core/graphicsConversions.h>
20
+ #include <react/renderer/core/propsConversions.h>
21
+ #include <react/renderer/debug/debugStringConvertibleUtils.h>
22
+ #include <react/renderer/graphics/ValueUnit.h>
23
+
24
+ namespace facebook::react {
25
+
26
+ namespace {
27
+
28
+ std::array<float, 3> getTranslateForTransformOrigin(
29
+ float viewWidth,
30
+ float viewHeight,
31
+ TransformOrigin transformOrigin) {
32
+ float viewCenterX = viewWidth / 2;
33
+ float viewCenterY = viewHeight / 2;
34
+
35
+ std::array<float, 3> origin = {viewCenterX, viewCenterY, transformOrigin.z};
36
+
37
+ for (size_t i = 0; i < transformOrigin.xy.size(); ++i) {
38
+ auto& currentOrigin = transformOrigin.xy[i];
39
+ if (currentOrigin.unit == UnitType::Point) {
40
+ origin[i] = currentOrigin.value;
41
+ } else if (currentOrigin.unit == UnitType::Percent) {
42
+ origin[i] =
43
+ ((i == 0) ? viewWidth : viewHeight) * currentOrigin.value / 100.0f;
44
+ }
45
+ }
46
+
47
+ float newTranslateX = -viewCenterX + origin[0];
48
+ float newTranslateY = -viewCenterY + origin[1];
49
+ float newTranslateZ = origin[2];
50
+
51
+ return std::array{newTranslateX, newTranslateY, newTranslateZ};
52
+ }
53
+
54
+ } // namespace
55
+
56
+ BaseViewProps::BaseViewProps(
57
+ const PropsParserContext& context,
58
+ const BaseViewProps& sourceProps,
59
+ const RawProps& rawProps,
60
+ const std::function<bool(const std::string&)>& filterObjectKeys)
61
+ : YogaStylableProps(context, sourceProps, rawProps, filterObjectKeys),
62
+ AccessibilityProps(context, sourceProps, rawProps),
63
+ opacity(
64
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
65
+ ? sourceProps.opacity
66
+ : convertRawProp(
67
+ context,
68
+ rawProps,
69
+ "opacity",
70
+ sourceProps.opacity,
71
+ (Float)1.0)),
72
+ backgroundColor(
73
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
74
+ ? sourceProps.backgroundColor
75
+ : convertRawProp(
76
+ context,
77
+ rawProps,
78
+ "backgroundColor",
79
+ sourceProps.backgroundColor,
80
+ {})),
81
+ borderRadii(
82
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
83
+ ? sourceProps.borderRadii
84
+ : convertRawProp(
85
+ context,
86
+ rawProps,
87
+ "border",
88
+ "Radius",
89
+ sourceProps.borderRadii,
90
+ {})),
91
+ borderColors(
92
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
93
+ ? sourceProps.borderColors
94
+ : convertRawProp(
95
+ context,
96
+ rawProps,
97
+ "border",
98
+ "Color",
99
+ sourceProps.borderColors,
100
+ {})),
101
+ borderCurves(
102
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
103
+ ? sourceProps.borderCurves
104
+ : convertRawProp(
105
+ context,
106
+ rawProps,
107
+ "border",
108
+ "Curve",
109
+ sourceProps.borderCurves,
110
+ {})),
111
+ borderStyles(
112
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
113
+ ? sourceProps.borderStyles
114
+ : convertRawProp(
115
+ context,
116
+ rawProps,
117
+ "border",
118
+ "Style",
119
+ sourceProps.borderStyles,
120
+ {})),
121
+ outlineColor(
122
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
123
+ ? sourceProps.outlineColor
124
+ : convertRawProp(
125
+ context,
126
+ rawProps,
127
+ "outlineColor",
128
+ sourceProps.outlineColor,
129
+ {})),
130
+ outlineOffset(
131
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
132
+ ? sourceProps.outlineOffset
133
+ : convertRawProp(
134
+ context,
135
+ rawProps,
136
+ "outlineOffset",
137
+ sourceProps.outlineOffset,
138
+ {})),
139
+ outlineStyle(
140
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
141
+ ? sourceProps.outlineStyle
142
+ : convertRawProp(
143
+ context,
144
+ rawProps,
145
+ "outlineStyle",
146
+ sourceProps.outlineStyle,
147
+ {})),
148
+ outlineWidth(
149
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
150
+ ? sourceProps.outlineWidth
151
+ : convertRawProp(
152
+ context,
153
+ rawProps,
154
+ "outlineWidth",
155
+ sourceProps.outlineWidth,
156
+ {})),
157
+ shadowColor(
158
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
159
+ ? sourceProps.shadowColor
160
+ : convertRawProp(
161
+ context,
162
+ rawProps,
163
+ "shadowColor",
164
+ sourceProps.shadowColor,
165
+ {})),
166
+ shadowOffset(
167
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
168
+ ? sourceProps.shadowOffset
169
+ : convertRawProp(
170
+ context,
171
+ rawProps,
172
+ "shadowOffset",
173
+ sourceProps.shadowOffset,
174
+ {})),
175
+ shadowOpacity(
176
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
177
+ ? sourceProps.shadowOpacity
178
+ : convertRawProp(
179
+ context,
180
+ rawProps,
181
+ "shadowOpacity",
182
+ sourceProps.shadowOpacity,
183
+ {})),
184
+ shadowRadius(
185
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
186
+ ? sourceProps.shadowRadius
187
+ : convertRawProp(
188
+ context,
189
+ rawProps,
190
+ "shadowRadius",
191
+ sourceProps.shadowRadius,
192
+ {})),
193
+ cursor(
194
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
195
+ ? sourceProps.cursor
196
+ : convertRawProp(
197
+ context,
198
+ rawProps,
199
+ "cursor",
200
+ sourceProps.cursor,
201
+ {})),
202
+ boxShadow(
203
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
204
+ ? sourceProps.boxShadow
205
+ : convertRawProp(
206
+ context,
207
+ rawProps,
208
+ "boxShadow",
209
+ sourceProps.boxShadow,
210
+ {})),
211
+ filter(
212
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
213
+ ? sourceProps.filter
214
+ : convertRawProp(
215
+ context,
216
+ rawProps,
217
+ "filter",
218
+ sourceProps.filter,
219
+ {})),
220
+ backgroundImage(
221
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
222
+ ? sourceProps.backgroundImage
223
+ : convertRawProp(
224
+ context,
225
+ rawProps,
226
+ "experimental_backgroundImage",
227
+ sourceProps.backgroundImage,
228
+ {})),
229
+ backgroundSize(
230
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
231
+ ? sourceProps.backgroundSize
232
+ : convertRawProp(
233
+ context,
234
+ rawProps,
235
+ "experimental_backgroundSize",
236
+ sourceProps.backgroundSize,
237
+ {})),
238
+ backgroundPosition(
239
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
240
+ ? sourceProps.backgroundPosition
241
+ : convertRawProp(
242
+ context,
243
+ rawProps,
244
+ "experimental_backgroundPosition",
245
+ sourceProps.backgroundPosition,
246
+ {})),
247
+ backgroundRepeat(
248
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
249
+ ? sourceProps.backgroundRepeat
250
+ : convertRawProp(
251
+ context,
252
+ rawProps,
253
+ "experimental_backgroundRepeat",
254
+ sourceProps.backgroundRepeat,
255
+ {})),
256
+ mixBlendMode(
257
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
258
+ ? sourceProps.mixBlendMode
259
+ : convertRawProp(
260
+ context,
261
+ rawProps,
262
+ "mixBlendMode",
263
+ sourceProps.mixBlendMode,
264
+ {})),
265
+ isolation(
266
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
267
+ ? sourceProps.isolation
268
+ : convertRawProp(
269
+ context,
270
+ rawProps,
271
+ "isolation",
272
+ sourceProps.isolation,
273
+ {})),
274
+ transform(
275
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
276
+ ? sourceProps.transform
277
+ : convertRawProp(
278
+ context,
279
+ rawProps,
280
+ "transform",
281
+ sourceProps.transform,
282
+ {})),
283
+ transformOrigin(
284
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
285
+ ? sourceProps.transformOrigin
286
+ : convertRawProp(
287
+ context,
288
+ rawProps,
289
+ "transformOrigin",
290
+ sourceProps.transformOrigin,
291
+ {})),
292
+ backfaceVisibility(
293
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
294
+ ? sourceProps.backfaceVisibility
295
+ : convertRawProp(
296
+ context,
297
+ rawProps,
298
+ "backfaceVisibility",
299
+ sourceProps.backfaceVisibility,
300
+ {})),
301
+ shouldRasterize(
302
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
303
+ ? sourceProps.shouldRasterize
304
+ : convertRawProp(
305
+ context,
306
+ rawProps,
307
+ "shouldRasterizeIOS",
308
+ sourceProps.shouldRasterize,
309
+ {})),
310
+ zIndex(
311
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
312
+ ? sourceProps.zIndex
313
+ : convertRawProp(
314
+ context,
315
+ rawProps,
316
+ "zIndex",
317
+ sourceProps.zIndex,
318
+ {})),
319
+ pointerEvents(
320
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
321
+ ? sourceProps.pointerEvents
322
+ : convertRawProp(
323
+ context,
324
+ rawProps,
325
+ "pointerEvents",
326
+ sourceProps.pointerEvents,
327
+ {})),
328
+ hitSlop(
329
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
330
+ ? sourceProps.hitSlop
331
+ : convertRawProp(
332
+ context,
333
+ rawProps,
334
+ "hitSlop",
335
+ sourceProps.hitSlop,
336
+ {})),
337
+ onLayout(
338
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
339
+ ? sourceProps.onLayout
340
+ : convertRawProp(
341
+ context,
342
+ rawProps,
343
+ "onLayout",
344
+ sourceProps.onLayout,
345
+ {})),
346
+ events(
347
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
348
+ ? sourceProps.events
349
+ : convertRawProp(context, rawProps, sourceProps.events, {})),
350
+ collapsable(
351
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
352
+ ? sourceProps.collapsable
353
+ : convertRawProp(
354
+ context,
355
+ rawProps,
356
+ "collapsable",
357
+ sourceProps.collapsable,
358
+ true)),
359
+ collapsableChildren(
360
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
361
+ ? sourceProps.collapsableChildren
362
+ : convertRawProp(
363
+ context,
364
+ rawProps,
365
+ "collapsableChildren",
366
+ sourceProps.collapsableChildren,
367
+ true)),
368
+ removeClippedSubviews(
369
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
370
+ ? sourceProps.removeClippedSubviews
371
+ : convertRawProp(
372
+ context,
373
+ rawProps,
374
+ "removeClippedSubviews",
375
+ sourceProps.removeClippedSubviews,
376
+ false)) {}
377
+
378
+ #define VIEW_EVENT_CASE(eventType) \
379
+ case CONSTEXPR_RAW_PROPS_KEY_HASH("on" #eventType): { \
380
+ const auto offset = ViewEvents::Offset::eventType; \
381
+ ViewEvents defaultViewEvents{}; \
382
+ bool res = defaultViewEvents[offset]; \
383
+ if (value.hasValue()) { \
384
+ fromRawValue(context, value, res); \
385
+ } \
386
+ events[offset] = res; \
387
+ return; \
388
+ }
389
+
390
+ void BaseViewProps::setProp(
391
+ const PropsParserContext& context,
392
+ RawPropsPropNameHash hash,
393
+ const char* propName,
394
+ const RawValue& value) {
395
+ // All Props structs setProp methods must always, unconditionally,
396
+ // call all super::setProp methods, since multiple structs may
397
+ // reuse the same values.
398
+ YogaStylableProps::setProp(context, hash, propName, value);
399
+ AccessibilityProps::setProp(context, hash, propName, value);
400
+
401
+ static auto defaults = BaseViewProps{};
402
+
403
+ switch (hash) {
404
+ RAW_SET_PROP_SWITCH_CASE_BASIC(opacity);
405
+ RAW_SET_PROP_SWITCH_CASE_BASIC(backgroundColor);
406
+ RAW_SET_PROP_SWITCH_CASE(backgroundImage, "experimental_backgroundImage");
407
+ RAW_SET_PROP_SWITCH_CASE(backgroundSize, "experimental_backgroundSize");
408
+ RAW_SET_PROP_SWITCH_CASE(
409
+ backgroundPosition, "experimental_backgroundPosition");
410
+ RAW_SET_PROP_SWITCH_CASE(backgroundRepeat, "experimental_backgroundRepeat");
411
+ RAW_SET_PROP_SWITCH_CASE_BASIC(shadowColor);
412
+ RAW_SET_PROP_SWITCH_CASE_BASIC(shadowOffset);
413
+ RAW_SET_PROP_SWITCH_CASE_BASIC(shadowOpacity);
414
+ RAW_SET_PROP_SWITCH_CASE_BASIC(shadowRadius);
415
+ RAW_SET_PROP_SWITCH_CASE_BASIC(transform);
416
+ RAW_SET_PROP_SWITCH_CASE_BASIC(backfaceVisibility);
417
+ RAW_SET_PROP_SWITCH_CASE_BASIC(shouldRasterize);
418
+ RAW_SET_PROP_SWITCH_CASE_BASIC(zIndex);
419
+ RAW_SET_PROP_SWITCH_CASE_BASIC(pointerEvents);
420
+ RAW_SET_PROP_SWITCH_CASE_BASIC(isolation);
421
+ RAW_SET_PROP_SWITCH_CASE_BASIC(hitSlop);
422
+ RAW_SET_PROP_SWITCH_CASE_BASIC(onLayout);
423
+ RAW_SET_PROP_SWITCH_CASE_BASIC(collapsable);
424
+ RAW_SET_PROP_SWITCH_CASE_BASIC(collapsableChildren);
425
+ RAW_SET_PROP_SWITCH_CASE_BASIC(removeClippedSubviews);
426
+ RAW_SET_PROP_SWITCH_CASE_BASIC(cursor);
427
+ RAW_SET_PROP_SWITCH_CASE_BASIC(outlineColor);
428
+ RAW_SET_PROP_SWITCH_CASE_BASIC(outlineOffset);
429
+ RAW_SET_PROP_SWITCH_CASE_BASIC(outlineStyle);
430
+ RAW_SET_PROP_SWITCH_CASE_BASIC(outlineWidth);
431
+ RAW_SET_PROP_SWITCH_CASE_BASIC(filter);
432
+ RAW_SET_PROP_SWITCH_CASE_BASIC(boxShadow);
433
+ RAW_SET_PROP_SWITCH_CASE_BASIC(mixBlendMode);
434
+ // events field
435
+ VIEW_EVENT_CASE(PointerEnter);
436
+ VIEW_EVENT_CASE(PointerEnterCapture);
437
+ VIEW_EVENT_CASE(PointerMove);
438
+ VIEW_EVENT_CASE(PointerMoveCapture);
439
+ VIEW_EVENT_CASE(PointerLeave);
440
+ VIEW_EVENT_CASE(PointerLeaveCapture);
441
+ VIEW_EVENT_CASE(PointerOver);
442
+ VIEW_EVENT_CASE(PointerOverCapture);
443
+ VIEW_EVENT_CASE(PointerOut);
444
+ VIEW_EVENT_CASE(PointerOutCapture);
445
+ // [Windows
446
+ VIEW_EVENT_CASE(Click);
447
+ VIEW_EVENT_CASE(ClickCapture);
448
+ VIEW_EVENT_CASE(PointerDown);
449
+ VIEW_EVENT_CASE(PointerDownCapture);
450
+ VIEW_EVENT_CASE(PointerUp);
451
+ VIEW_EVENT_CASE(PointerUpCapture);
452
+ VIEW_EVENT_CASE(GotPointerCapture);
453
+ VIEW_EVENT_CASE(LostPointerCapture);
454
+ // Windows]
455
+ VIEW_EVENT_CASE(MoveShouldSetResponder);
456
+ VIEW_EVENT_CASE(MoveShouldSetResponderCapture);
457
+ VIEW_EVENT_CASE(StartShouldSetResponder);
458
+ VIEW_EVENT_CASE(StartShouldSetResponderCapture);
459
+ VIEW_EVENT_CASE(ResponderGrant);
460
+ VIEW_EVENT_CASE(ResponderReject);
461
+ VIEW_EVENT_CASE(ResponderStart);
462
+ VIEW_EVENT_CASE(ResponderEnd);
463
+ VIEW_EVENT_CASE(ResponderRelease);
464
+ VIEW_EVENT_CASE(ResponderMove);
465
+ VIEW_EVENT_CASE(ResponderTerminate);
466
+ VIEW_EVENT_CASE(ResponderTerminationRequest);
467
+ VIEW_EVENT_CASE(ShouldBlockNativeResponder);
468
+ VIEW_EVENT_CASE(TouchStart);
469
+ VIEW_EVENT_CASE(TouchMove);
470
+ VIEW_EVENT_CASE(TouchEnd);
471
+ VIEW_EVENT_CASE(TouchCancel);
472
+ // BorderRadii
473
+ SET_CASCADED_RECTANGLE_CORNERS(borderRadii, "border", "Radius", value);
474
+ SET_CASCADED_RECTANGLE_EDGES(borderColors, "border", "Color", value);
475
+ SET_CASCADED_RECTANGLE_EDGES(borderStyles, "border", "Style", value);
476
+ }
477
+ }
478
+
479
+ #pragma mark - Convenience Methods
480
+
481
+ static BorderRadii ensureNoOverlap(const BorderRadii& radii, const Size& size) {
482
+ // "Corner curves must not overlap: When the sum of any two adjacent border
483
+ // radii exceeds the size of the border box, UAs must proportionally reduce
484
+ // the used values of all border radii until none of them overlap."
485
+ // Source: https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
486
+
487
+ float leftEdgeRadii = radii.topLeft.vertical + radii.bottomLeft.vertical;
488
+ float topEdgeRadii = radii.topLeft.horizontal + radii.topRight.horizontal;
489
+ float rightEdgeRadii = radii.topRight.vertical + radii.bottomRight.vertical;
490
+ float bottomEdgeRadii =
491
+ radii.bottomLeft.horizontal + radii.bottomRight.horizontal;
492
+
493
+ float leftEdgeRadiiScale =
494
+ (leftEdgeRadii > 0) ? std::min(size.height / leftEdgeRadii, (Float)1) : 0;
495
+ float topEdgeRadiiScale =
496
+ (topEdgeRadii > 0) ? std::min(size.width / topEdgeRadii, (Float)1) : 0;
497
+ float rightEdgeRadiiScale = (rightEdgeRadii > 0)
498
+ ? std::min(size.height / rightEdgeRadii, (Float)1)
499
+ : 0;
500
+ float bottomEdgeRadiiScale = (bottomEdgeRadii > 0)
501
+ ? std::min(size.width / bottomEdgeRadii, (Float)1)
502
+ : 0;
503
+
504
+ return BorderRadii{
505
+ .topLeft =
506
+ {static_cast<float>(
507
+ radii.topLeft.vertical *
508
+ std::min(topEdgeRadiiScale, leftEdgeRadiiScale)),
509
+ static_cast<float>(
510
+ radii.topLeft.horizontal *
511
+ std::min(topEdgeRadiiScale, leftEdgeRadiiScale))},
512
+ .topRight =
513
+ {static_cast<float>(
514
+ radii.topRight.vertical *
515
+ std::min(topEdgeRadiiScale, rightEdgeRadiiScale)),
516
+ static_cast<float>(
517
+ radii.topRight.horizontal *
518
+ std::min(topEdgeRadiiScale, rightEdgeRadiiScale))},
519
+ .bottomLeft =
520
+ {static_cast<float>(
521
+ radii.bottomLeft.vertical *
522
+ std::min(bottomEdgeRadiiScale, leftEdgeRadiiScale)),
523
+ static_cast<float>(
524
+ radii.bottomLeft.horizontal *
525
+ std::min(bottomEdgeRadiiScale, leftEdgeRadiiScale))},
526
+ .bottomRight =
527
+ {static_cast<float>(
528
+ radii.bottomRight.vertical *
529
+ std::min(bottomEdgeRadiiScale, rightEdgeRadiiScale)),
530
+ static_cast<float>(
531
+ radii.bottomRight.horizontal *
532
+ std::min(bottomEdgeRadiiScale, rightEdgeRadiiScale))},
533
+ };
534
+ }
535
+
536
+ static BorderRadii radiiPercentToPoint(
537
+ const RectangleCorners<ValueUnit>& radii,
538
+ const Size& size) {
539
+ return BorderRadii{
540
+ .topLeft =
541
+ {radii.topLeft.resolve(size.height),
542
+ radii.topLeft.resolve(size.width)},
543
+ .topRight =
544
+ {radii.topRight.resolve(size.height),
545
+ radii.topRight.resolve(size.width)},
546
+ .bottomLeft =
547
+ {radii.bottomLeft.resolve(size.height),
548
+ radii.bottomLeft.resolve(size.width)},
549
+ .bottomRight =
550
+ {radii.bottomRight.resolve(size.height),
551
+ radii.bottomRight.resolve(size.width)},
552
+ };
553
+ }
554
+
555
+ CascadedBorderWidths BaseViewProps::getBorderWidths() const {
556
+ return CascadedBorderWidths{
557
+ .left = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Left)),
558
+ .top = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Top)),
559
+ .right = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Right)),
560
+ .bottom =
561
+ optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Bottom)),
562
+ .start = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Start)),
563
+ .end = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::End)),
564
+ .horizontal =
565
+ optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Horizontal)),
566
+ .vertical =
567
+ optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Vertical)),
568
+ .all = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::All)),
569
+ };
570
+ }
571
+
572
+ BorderMetrics BaseViewProps::resolveBorderMetrics(
573
+ const LayoutMetrics& layoutMetrics) const {
574
+ auto isRTL =
575
+ bool{layoutMetrics.layoutDirection == LayoutDirection::RightToLeft};
576
+
577
+ auto borderWidths = getBorderWidths();
578
+
579
+ BorderRadii radii = radiiPercentToPoint(
580
+ borderRadii.resolve(isRTL, ValueUnit{0.0f, UnitType::Point}),
581
+ layoutMetrics.frame.size);
582
+
583
+ return {
584
+ .borderColors = borderColors.resolve(isRTL, {}),
585
+ .borderWidths = borderWidths.resolve(isRTL, 0),
586
+ .borderRadii = ensureNoOverlap(radii, layoutMetrics.frame.size),
587
+ .borderCurves = borderCurves.resolve(isRTL, BorderCurve::Circular),
588
+ .borderStyles = borderStyles.resolve(isRTL, BorderStyle::Solid),
589
+ };
590
+ }
591
+
592
+ Transform BaseViewProps::resolveTransform(
593
+ const LayoutMetrics& layoutMetrics) const {
594
+ const auto& frameSize = layoutMetrics.frame.size;
595
+ return resolveTransform(frameSize, transform, transformOrigin);
596
+ }
597
+
598
+ Transform BaseViewProps::resolveTransform(
599
+ const Size& frameSize,
600
+ const Transform& transform,
601
+ const TransformOrigin& transformOrigin) {
602
+ auto transformMatrix = Transform{};
603
+
604
+ // transform is matrix
605
+ if (transform.operations.size() == 1 &&
606
+ transform.operations[0].type == TransformOperationType::Arbitrary) {
607
+ transformMatrix = transform;
608
+ } else {
609
+ for (const auto& operation : transform.operations) {
610
+ transformMatrix = transformMatrix *
611
+ Transform::FromTransformOperation(operation, frameSize, transform);
612
+ }
613
+ }
614
+
615
+ if (transformOrigin.isSet()) {
616
+ std::array<float, 3> translateOffsets = getTranslateForTransformOrigin(
617
+ frameSize.width, frameSize.height, transformOrigin);
618
+ transformMatrix =
619
+ Transform::Translate(
620
+ translateOffsets[0], translateOffsets[1], translateOffsets[2]) *
621
+ transformMatrix *
622
+ Transform::Translate(
623
+ -translateOffsets[0], -translateOffsets[1], -translateOffsets[2]);
624
+ }
625
+
626
+ return transformMatrix;
627
+ }
628
+
629
+ bool BaseViewProps::getClipsContentToBounds() const {
630
+ return yogaStyle.overflow() != yoga::Overflow::Visible;
631
+ }
632
+
633
+ #pragma mark - DebugStringConvertible
634
+
635
+ #if RN_DEBUG_STRING_CONVERTIBLE
636
+ SharedDebugStringConvertibleList BaseViewProps::getDebugProps() const {
637
+ const auto& defaultBaseViewProps = BaseViewProps();
638
+
639
+ return AccessibilityProps::getDebugProps() +
640
+ YogaStylableProps::getDebugProps() +
641
+ SharedDebugStringConvertibleList{
642
+ debugStringConvertibleItem(
643
+ "opacity", opacity, defaultBaseViewProps.opacity),
644
+ debugStringConvertibleItem(
645
+ "backgroundColor",
646
+ backgroundColor,
647
+ defaultBaseViewProps.backgroundColor),
648
+ debugStringConvertibleItem(
649
+ "zIndex", zIndex, defaultBaseViewProps.zIndex.value_or(0)),
650
+ debugStringConvertibleItem(
651
+ "pointerEvents",
652
+ pointerEvents,
653
+ defaultBaseViewProps.pointerEvents),
654
+ debugStringConvertibleItem(
655
+ "transform", transform, defaultBaseViewProps.transform),
656
+ debugStringConvertibleItem(
657
+ "backgroundImage",
658
+ backgroundImage,
659
+ defaultBaseViewProps.backgroundImage),
660
+ };
661
+ }
662
+ #endif
663
+
664
+ } // namespace facebook::react
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-windows",
3
- "version": "0.83.0-preview.0",
3
+ "version": "0.83.0-preview.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,7 +26,7 @@
26
26
  "@react-native-community/cli": "20.0.0",
27
27
  "@react-native-community/cli-platform-android": "20.0.0",
28
28
  "@react-native-community/cli-platform-ios": "20.0.0",
29
- "@react-native-windows/cli": "0.83.0-preview.0",
29
+ "@react-native-windows/cli": "0.83.0-preview.1",
30
30
  "@react-native/assets": "1.0.0",
31
31
  "@react-native/assets-registry": "0.83.0-rc.5",
32
32
  "@react-native/codegen": "0.83.0-rc.5",
@@ -69,7 +69,7 @@
69
69
  "yargs": "^17.6.2"
70
70
  },
71
71
  "devDependencies": {
72
- "@react-native-windows/codegen": "0.83.0-preview.0",
72
+ "@react-native-windows/codegen": "0.83.0-preview.1",
73
73
  "@react-native/metro-config": "0.83.0-rc.5",
74
74
  "@rnw-scripts/babel-react-native-config": "0.0.0",
75
75
  "@rnw-scripts/eslint-config": "1.2.38",
@@ -86,7 +86,7 @@
86
86
  "prettier": "2.8.8",
87
87
  "react": "19.2.0",
88
88
  "react-native": "0.83.0-rc.5",
89
- "react-native-platform-override": "0.83.0-preview.0",
89
+ "react-native-platform-override": "0.83.0-preview.1",
90
90
  "react-refresh": "^0.14.0",
91
91
  "typescript": "5.0.4"
92
92
  },