react-native-windows 0.81.9 → 0.81.11

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;
@@ -226,6 +226,11 @@ winrt::hstring ViewProps::AccessibilityLabel() noexcept {
226
226
  return m_viewProps ? winrt::to_hstring(m_viewProps->accessibilityLabel) : winrt::hstring{};
227
227
  }
228
228
 
229
+ winrt::Microsoft::ReactNative::Overflow ViewProps::Overflow() noexcept {
230
+ return m_viewProps ? static_cast<winrt::Microsoft::ReactNative::Overflow>(m_viewProps->yogaStyle.overflow())
231
+ : winrt::Microsoft::ReactNative::Overflow::Visible;
232
+ }
233
+
229
234
  ImageProps::ImageProps(facebook::react::SharedViewProps props) noexcept : Super(props) {}
230
235
 
231
236
  winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::ReactNative::ImageSource>
@@ -101,6 +101,7 @@ struct ViewProps : ViewPropsT<ViewProps> {
101
101
  winrt::Microsoft::ReactNative::Color BackgroundColor() noexcept;
102
102
  winrt::hstring TestId() noexcept;
103
103
  winrt::hstring AccessibilityLabel() noexcept;
104
+ winrt::Microsoft::ReactNative::Overflow Overflow() noexcept;
104
105
 
105
106
  protected:
106
107
  facebook::react::SharedViewProps m_props;
@@ -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;
@@ -614,6 +614,8 @@ int64_t CompositionEventHandler::SendMessage(HWND hwnd, uint32_t msg, uint64_t w
614
614
 
615
615
  void CompositionEventHandler::onKeyDown(
616
616
  const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept {
617
+ RootComponentView().UseKeyboardForProgrammaticFocus(true);
618
+
617
619
  if (auto focusedComponent = RootComponentView().GetFocusedComponent()) {
618
620
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(focusedComponent)->OnKeyDown(args);
619
621
 
@@ -637,7 +639,7 @@ void CompositionEventHandler::onKeyDown(
637
639
  }
638
640
 
639
641
  if (!fCtrl && args.Key() == winrt::Windows::System::VirtualKey::Tab) {
640
- if (RootComponentView().TryMoveFocus(!fShift)) {
642
+ if (RootComponentView().TryMoveFocus(!fShift, winrt::Microsoft::ReactNative::FocusState::Keyboard)) {
641
643
  args.Handled(true);
642
644
  }
643
645
 
@@ -647,6 +649,8 @@ void CompositionEventHandler::onKeyDown(
647
649
 
648
650
  void CompositionEventHandler::onKeyUp(
649
651
  const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept {
652
+ RootComponentView().UseKeyboardForProgrammaticFocus(true);
653
+
650
654
  if (auto focusedComponent = RootComponentView().GetFocusedComponent()) {
651
655
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(focusedComponent)->OnKeyUp(args);
652
656
 
@@ -1179,6 +1183,8 @@ void CompositionEventHandler::onPointerPressed(
1179
1183
  winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept {
1180
1184
  namespace Composition = winrt::Microsoft::ReactNative::Composition;
1181
1185
 
1186
+ RootComponentView().UseKeyboardForProgrammaticFocus(false);
1187
+
1182
1188
  // Clears any active text selection when left pointer is pressed
1183
1189
  if (pointerPoint.Properties().PointerUpdateKind() != Composition::Input::PointerUpdateKind::RightButtonPressed) {
1184
1190
  RootComponentView().ClearCurrentTextSelection();
@@ -1216,6 +1222,30 @@ void CompositionEventHandler::onPointerPressed(
1216
1222
  ActiveTouch activeTouch{0};
1217
1223
  activeTouch.touchType = UITouchType::Mouse;
1218
1224
 
1225
+ // Map PointerUpdateKind to W3C button value
1226
+ // https://developer.mozilla.org/docs/Web/API/MouseEvent/button
1227
+ auto updateKind = pointerPoint.Properties().PointerUpdateKind();
1228
+ switch (updateKind) {
1229
+ case Composition::Input::PointerUpdateKind::LeftButtonPressed:
1230
+ activeTouch.button = 0;
1231
+ break;
1232
+ case Composition::Input::PointerUpdateKind::MiddleButtonPressed:
1233
+ activeTouch.button = 1;
1234
+ break;
1235
+ case Composition::Input::PointerUpdateKind::RightButtonPressed:
1236
+ activeTouch.button = 2;
1237
+ break;
1238
+ case Composition::Input::PointerUpdateKind::XButton1Pressed:
1239
+ activeTouch.button = 3;
1240
+ break;
1241
+ case Composition::Input::PointerUpdateKind::XButton2Pressed:
1242
+ activeTouch.button = 4;
1243
+ break;
1244
+ default:
1245
+ activeTouch.button = -1;
1246
+ break;
1247
+ }
1248
+
1219
1249
  while (targetComponentView) {
1220
1250
  if (auto eventEmitter =
1221
1251
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(targetComponentView)
@@ -1251,6 +1281,8 @@ void CompositionEventHandler::onPointerReleased(
1251
1281
  winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept {
1252
1282
  int pointerId = pointerPoint.PointerId();
1253
1283
 
1284
+ RootComponentView().UseKeyboardForProgrammaticFocus(false);
1285
+
1254
1286
  auto activeTouch = std::find_if(m_activeTouches.begin(), m_activeTouches.end(), [pointerId](const auto &pair) {
1255
1287
  return pair.second.touch.identifier == pointerId;
1256
1288
  });
@@ -1400,8 +1432,34 @@ facebook::react::PointerEvent CompositionEventHandler::CreatePointerEventFromAct
1400
1432
 
1401
1433
  event.detail = 0;
1402
1434
 
1403
- // event.button = activeTouch.button;
1404
- // event.buttons = ButtonMaskToButtons(activeTouch.buttonMask);
1435
+ event.button = activeTouch.button;
1436
+
1437
+ // Build W3C buttons bitmask from the active button
1438
+ // https://developer.mozilla.org/docs/Web/API/MouseEvent/buttons
1439
+ if (IsEndishEventType(eventType)) {
1440
+ event.buttons = 0;
1441
+ } else {
1442
+ switch (activeTouch.button) {
1443
+ case 0:
1444
+ event.buttons = 1;
1445
+ break; // primary
1446
+ case 1:
1447
+ event.buttons = 4;
1448
+ break; // auxiliary (middle)
1449
+ case 2:
1450
+ event.buttons = 2;
1451
+ break; // secondary (right)
1452
+ case 3:
1453
+ event.buttons = 8;
1454
+ break; // X1
1455
+ case 4:
1456
+ event.buttons = 16;
1457
+ break; // X2
1458
+ default:
1459
+ event.buttons = 0;
1460
+ break;
1461
+ }
1462
+ }
1405
1463
 
1406
1464
  // UpdatePointerEventModifierFlags(event, activeTouch.modifierFlags);
1407
1465
 
@@ -375,7 +375,8 @@ void ComponentView::onGotFocus(
375
375
  const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
376
376
  if (args.OriginalSource() == Tag()) {
377
377
  m_eventEmitter->onFocus();
378
- if (viewProps()->enableFocusRing) {
378
+ if (viewProps()->enableFocusRing &&
379
+ rootComponentView()->focusState() == winrt::Microsoft::ReactNative::FocusState::Keyboard) {
379
380
  facebook::react::Rect focusRect = m_layoutMetrics.frame;
380
381
  focusRect.origin.x -= (FOCUS_VISUAL_WIDTH * 2);
381
382
  focusRect.origin.y -= (FOCUS_VISUAL_WIDTH * 2);
@@ -428,15 +429,20 @@ void ComponentView::HandleCommand(const winrt::Microsoft::ReactNative::HandleCom
428
429
  auto commandName = args.CommandName();
429
430
  if (commandName == L"focus") {
430
431
  if (auto root = rootComponentView()) {
431
- root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
432
+ root->TrySetFocusedComponent(
433
+ *get_strong(),
434
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
435
+ winrt::Microsoft::ReactNative::FocusState::Programmatic);
432
436
  }
433
437
  return;
434
438
  }
435
439
  if (commandName == L"blur") {
436
440
  if (auto root = rootComponentView()) {
437
441
  root->TrySetFocusedComponent(
438
- nullptr, winrt::Microsoft::ReactNative::FocusNavigationDirection::None); // Todo store this component as
439
- // previously focused element
442
+ nullptr,
443
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
444
+ winrt::Microsoft::ReactNative::FocusState::Programmatic); // Todo store this component as
445
+ // previously focused element
440
446
  }
441
447
  return;
442
448
  }
@@ -1176,15 +1182,17 @@ facebook::react::Tag ViewComponentView::hitTest(
1176
1182
 
1177
1183
  facebook::react::Tag targetTag = -1;
1178
1184
 
1185
+ bool isPointInside = ptLocal.x >= 0 && ptLocal.x <= m_layoutMetrics.frame.size.width && ptLocal.y >= 0 &&
1186
+ ptLocal.y <= m_layoutMetrics.frame.size.height;
1187
+
1179
1188
  if ((ignorePointerEvents || m_props->pointerEvents == facebook::react::PointerEventsMode::Auto ||
1180
1189
  m_props->pointerEvents == facebook::react::PointerEventsMode::BoxNone) &&
1181
- anyHitTestHelper(targetTag, ptLocal, localPt))
1190
+ (isPointInside || !viewProps()->getClipsContentToBounds()) && anyHitTestHelper(targetTag, ptLocal, localPt))
1182
1191
  return targetTag;
1183
1192
 
1184
1193
  if ((ignorePointerEvents || m_props->pointerEvents == facebook::react::PointerEventsMode::Auto ||
1185
1194
  m_props->pointerEvents == facebook::react::PointerEventsMode::BoxOnly) &&
1186
- ptLocal.x >= 0 && ptLocal.x <= m_layoutMetrics.frame.size.width && ptLocal.y >= 0 &&
1187
- ptLocal.y <= m_layoutMetrics.frame.size.height) {
1195
+ isPointInside) {
1188
1196
  localPt = ptLocal;
1189
1197
  return Tag();
1190
1198
  }
@@ -1342,6 +1350,10 @@ void ViewComponentView::updateLayoutMetrics(
1342
1350
  void ViewComponentView::updateChildrenClippingPath(
1343
1351
  facebook::react::LayoutMetrics const &layoutMetrics,
1344
1352
  const facebook::react::ViewProps &viewProps) noexcept {
1353
+ // Views with a custom visual to mount children into should to do their own handling of children clipping path
1354
+ if (m_builder && m_builder->VisualToMountChildrenIntoHandler())
1355
+ return;
1356
+
1345
1357
  const float scale = layoutMetrics.pointScaleFactor;
1346
1358
  const float viewWidth = layoutMetrics.frame.size.width * scale;
1347
1359
  const float viewHeight = layoutMetrics.frame.size.height * scale;
@@ -83,7 +83,7 @@ void ContentIslandComponentView::ConnectInternal() noexcept {
83
83
  m_navigationHost.DepartFocusRequested([wkThis = get_weak()](const auto &, const auto &args) {
84
84
  if (auto strongThis = wkThis.get()) {
85
85
  const bool next = (args.Request().Reason() != winrt::Microsoft::UI::Input::FocusNavigationReason::Last);
86
- strongThis->rootComponentView()->TryMoveFocus(next);
86
+ strongThis->rootComponentView()->TryMoveFocus(next, winrt::Microsoft::ReactNative::FocusState::Programmatic);
87
87
  args.Result(winrt::Microsoft::UI::Input::FocusNavigationResult::Moved);
88
88
  }
89
89
  });
@@ -613,7 +613,10 @@ void ParagraphComponentView::OnPointerPressed(
613
613
 
614
614
  // Focuses so we receive onLostFocus when clicking elsewhere
615
615
  if (auto root = rootComponentView()) {
616
- root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
616
+ root->TrySetFocusedComponent(
617
+ *get_strong(),
618
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
619
+ winrt::Microsoft::ReactNative::FocusState::Pointer);
617
620
  }
618
621
 
619
622
  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
  }
@@ -72,6 +72,8 @@ namespace Microsoft.ReactNative.Composition
72
72
  void SetCreateVisualHandler(CreateVisualDelegate impl);
73
73
  void SetViewFeatures(ComponentViewFeatures viewFeatures);
74
74
  void SetUpdateLayoutMetricsHandler(UpdateLayoutMetricsDelegate impl);
75
+
76
+ DOC_STRING("Provides a customized ContainerVisual that this components children will be mounted into. When overriding this, a clip is no longer automatically applied for overflow:\"hidden\"")
75
77
  void SetVisualToMountChildrenIntoHandler(VisualToMountChildrenIntoDelegate impl);
76
78
  };
77
79
 
@@ -32,6 +32,14 @@ namespace Microsoft.ReactNative {
32
32
  static void WriteValue(IJSValueWriter writer, Color color);
33
33
  };
34
34
 
35
+ [experimental]
36
+ enum Overflow
37
+ {
38
+ Visible,
39
+ Hidden,
40
+ Scroll,
41
+ };
42
+
35
43
  [webhosthidden]
36
44
  [experimental]
37
45
  DOC_STRING("Interface to implement custom view component properties.")
@@ -53,6 +61,7 @@ namespace Microsoft.ReactNative {
53
61
  Color BackgroundColor { get; };
54
62
  String TestId { get; };
55
63
  String AccessibilityLabel { get; };
64
+ Overflow Overflow { get; };
56
65
 
57
66
  // TODO add accessors to all the properties on ViewProps
58
67
  };
@@ -10,11 +10,11 @@
10
10
  -->
11
11
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
12
12
  <PropertyGroup>
13
- <ReactNativeWindowsVersion>0.81.9</ReactNativeWindowsVersion>
13
+ <ReactNativeWindowsVersion>0.81.11</ReactNativeWindowsVersion>
14
14
  <ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
15
15
  <ReactNativeWindowsMinor>81</ReactNativeWindowsMinor>
16
- <ReactNativeWindowsPatch>9</ReactNativeWindowsPatch>
16
+ <ReactNativeWindowsPatch>11</ReactNativeWindowsPatch>
17
17
  <ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
18
- <ReactNativeWindowsCommitId>1933bc69992ad9f199d0b2ebfa7ded80b141655e</ReactNativeWindowsCommitId>
18
+ <ReactNativeWindowsCommitId>a964ab588ab12db0b975f848c88d7a0b750d6cba</ReactNativeWindowsCommitId>
19
19
  </PropertyGroup>
20
20
  </Project>
@@ -0,0 +1,628 @@
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/BoxShadowPropsConversions.h>
14
+ #include <react/renderer/components/view/FilterPropsConversions.h>
15
+ #include <react/renderer/components/view/conversions.h>
16
+ #include <react/renderer/components/view/primitives.h>
17
+ #include <react/renderer/components/view/propsConversions.h>
18
+ #include <react/renderer/core/graphicsConversions.h>
19
+ #include <react/renderer/core/propsConversions.h>
20
+ #include <react/renderer/debug/debugStringConvertibleUtils.h>
21
+ #include <react/renderer/graphics/ValueUnit.h>
22
+
23
+ namespace facebook::react {
24
+
25
+ namespace {
26
+
27
+ std::array<float, 3> getTranslateForTransformOrigin(
28
+ float viewWidth,
29
+ float viewHeight,
30
+ TransformOrigin transformOrigin) {
31
+ float viewCenterX = viewWidth / 2;
32
+ float viewCenterY = viewHeight / 2;
33
+
34
+ std::array<float, 3> origin = {viewCenterX, viewCenterY, transformOrigin.z};
35
+
36
+ for (size_t i = 0; i < transformOrigin.xy.size(); ++i) {
37
+ auto& currentOrigin = transformOrigin.xy[i];
38
+ if (currentOrigin.unit == UnitType::Point) {
39
+ origin[i] = currentOrigin.value;
40
+ } else if (currentOrigin.unit == UnitType::Percent) {
41
+ origin[i] =
42
+ ((i == 0) ? viewWidth : viewHeight) * currentOrigin.value / 100.0f;
43
+ }
44
+ }
45
+
46
+ float newTranslateX = -viewCenterX + origin[0];
47
+ float newTranslateY = -viewCenterY + origin[1];
48
+ float newTranslateZ = origin[2];
49
+
50
+ return std::array{newTranslateX, newTranslateY, newTranslateZ};
51
+ }
52
+
53
+ } // namespace
54
+
55
+ BaseViewProps::BaseViewProps(
56
+ const PropsParserContext& context,
57
+ const BaseViewProps& sourceProps,
58
+ const RawProps& rawProps,
59
+ const std::function<bool(const std::string&)>& filterObjectKeys)
60
+ : YogaStylableProps(context, sourceProps, rawProps, filterObjectKeys),
61
+ AccessibilityProps(context, sourceProps, rawProps),
62
+ opacity(
63
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
64
+ ? sourceProps.opacity
65
+ : convertRawProp(
66
+ context,
67
+ rawProps,
68
+ "opacity",
69
+ sourceProps.opacity,
70
+ (Float)1.0)),
71
+ backgroundColor(
72
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
73
+ ? sourceProps.backgroundColor
74
+ : convertRawProp(
75
+ context,
76
+ rawProps,
77
+ "backgroundColor",
78
+ sourceProps.backgroundColor,
79
+ {})),
80
+ borderRadii(
81
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
82
+ ? sourceProps.borderRadii
83
+ : convertRawProp(
84
+ context,
85
+ rawProps,
86
+ "border",
87
+ "Radius",
88
+ sourceProps.borderRadii,
89
+ {})),
90
+ borderColors(
91
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
92
+ ? sourceProps.borderColors
93
+ : convertRawProp(
94
+ context,
95
+ rawProps,
96
+ "border",
97
+ "Color",
98
+ sourceProps.borderColors,
99
+ {})),
100
+ borderCurves(
101
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
102
+ ? sourceProps.borderCurves
103
+ : convertRawProp(
104
+ context,
105
+ rawProps,
106
+ "border",
107
+ "Curve",
108
+ sourceProps.borderCurves,
109
+ {})),
110
+ borderStyles(
111
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
112
+ ? sourceProps.borderStyles
113
+ : convertRawProp(
114
+ context,
115
+ rawProps,
116
+ "border",
117
+ "Style",
118
+ sourceProps.borderStyles,
119
+ {})),
120
+ outlineColor(
121
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
122
+ ? sourceProps.outlineColor
123
+ : convertRawProp(
124
+ context,
125
+ rawProps,
126
+ "outlineColor",
127
+ sourceProps.outlineColor,
128
+ {})),
129
+ outlineOffset(
130
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
131
+ ? sourceProps.outlineOffset
132
+ : convertRawProp(
133
+ context,
134
+ rawProps,
135
+ "outlineOffset",
136
+ sourceProps.outlineOffset,
137
+ {})),
138
+ outlineStyle(
139
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
140
+ ? sourceProps.outlineStyle
141
+ : convertRawProp(
142
+ context,
143
+ rawProps,
144
+ "outlineStyle",
145
+ sourceProps.outlineStyle,
146
+ {})),
147
+ outlineWidth(
148
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
149
+ ? sourceProps.outlineWidth
150
+ : convertRawProp(
151
+ context,
152
+ rawProps,
153
+ "outlineWidth",
154
+ sourceProps.outlineWidth,
155
+ {})),
156
+ shadowColor(
157
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
158
+ ? sourceProps.shadowColor
159
+ : convertRawProp(
160
+ context,
161
+ rawProps,
162
+ "shadowColor",
163
+ sourceProps.shadowColor,
164
+ {})),
165
+ shadowOffset(
166
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
167
+ ? sourceProps.shadowOffset
168
+ : convertRawProp(
169
+ context,
170
+ rawProps,
171
+ "shadowOffset",
172
+ sourceProps.shadowOffset,
173
+ {})),
174
+ shadowOpacity(
175
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
176
+ ? sourceProps.shadowOpacity
177
+ : convertRawProp(
178
+ context,
179
+ rawProps,
180
+ "shadowOpacity",
181
+ sourceProps.shadowOpacity,
182
+ {})),
183
+ shadowRadius(
184
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
185
+ ? sourceProps.shadowRadius
186
+ : convertRawProp(
187
+ context,
188
+ rawProps,
189
+ "shadowRadius",
190
+ sourceProps.shadowRadius,
191
+ {})),
192
+ cursor(
193
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
194
+ ? sourceProps.cursor
195
+ : convertRawProp(
196
+ context,
197
+ rawProps,
198
+ "cursor",
199
+ sourceProps.cursor,
200
+ {})),
201
+ boxShadow(
202
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
203
+ ? sourceProps.boxShadow
204
+ : convertRawProp(
205
+ context,
206
+ rawProps,
207
+ "boxShadow",
208
+ sourceProps.boxShadow,
209
+ {})),
210
+ filter(
211
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
212
+ ? sourceProps.filter
213
+ : convertRawProp(
214
+ context,
215
+ rawProps,
216
+ "filter",
217
+ sourceProps.filter,
218
+ {})),
219
+ backgroundImage(
220
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
221
+ ? sourceProps.backgroundImage
222
+ : convertRawProp(
223
+ context,
224
+ rawProps,
225
+ "experimental_backgroundImage",
226
+ sourceProps.backgroundImage,
227
+ {})),
228
+ mixBlendMode(
229
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
230
+ ? sourceProps.mixBlendMode
231
+ : convertRawProp(
232
+ context,
233
+ rawProps,
234
+ "mixBlendMode",
235
+ sourceProps.mixBlendMode,
236
+ {})),
237
+ isolation(
238
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
239
+ ? sourceProps.isolation
240
+ : convertRawProp(
241
+ context,
242
+ rawProps,
243
+ "isolation",
244
+ sourceProps.isolation,
245
+ {})),
246
+ transform(
247
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
248
+ ? sourceProps.transform
249
+ : convertRawProp(
250
+ context,
251
+ rawProps,
252
+ "transform",
253
+ sourceProps.transform,
254
+ {})),
255
+ transformOrigin(
256
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
257
+ ? sourceProps.transformOrigin
258
+ : convertRawProp(
259
+ context,
260
+ rawProps,
261
+ "transformOrigin",
262
+ sourceProps.transformOrigin,
263
+ {})),
264
+ backfaceVisibility(
265
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
266
+ ? sourceProps.backfaceVisibility
267
+ : convertRawProp(
268
+ context,
269
+ rawProps,
270
+ "backfaceVisibility",
271
+ sourceProps.backfaceVisibility,
272
+ {})),
273
+ shouldRasterize(
274
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
275
+ ? sourceProps.shouldRasterize
276
+ : convertRawProp(
277
+ context,
278
+ rawProps,
279
+ "shouldRasterizeIOS",
280
+ sourceProps.shouldRasterize,
281
+ {})),
282
+ zIndex(
283
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
284
+ ? sourceProps.zIndex
285
+ : convertRawProp(
286
+ context,
287
+ rawProps,
288
+ "zIndex",
289
+ sourceProps.zIndex,
290
+ {})),
291
+ pointerEvents(
292
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
293
+ ? sourceProps.pointerEvents
294
+ : convertRawProp(
295
+ context,
296
+ rawProps,
297
+ "pointerEvents",
298
+ sourceProps.pointerEvents,
299
+ {})),
300
+ hitSlop(
301
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
302
+ ? sourceProps.hitSlop
303
+ : convertRawProp(
304
+ context,
305
+ rawProps,
306
+ "hitSlop",
307
+ sourceProps.hitSlop,
308
+ {})),
309
+ onLayout(
310
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
311
+ ? sourceProps.onLayout
312
+ : convertRawProp(
313
+ context,
314
+ rawProps,
315
+ "onLayout",
316
+ sourceProps.onLayout,
317
+ {})),
318
+ events(
319
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
320
+ ? sourceProps.events
321
+ : convertRawProp(context, rawProps, sourceProps.events, {})),
322
+ collapsable(
323
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
324
+ ? sourceProps.collapsable
325
+ : convertRawProp(
326
+ context,
327
+ rawProps,
328
+ "collapsable",
329
+ sourceProps.collapsable,
330
+ true)),
331
+ collapsableChildren(
332
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
333
+ ? sourceProps.collapsableChildren
334
+ : convertRawProp(
335
+ context,
336
+ rawProps,
337
+ "collapsableChildren",
338
+ sourceProps.collapsableChildren,
339
+ true)),
340
+ removeClippedSubviews(
341
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
342
+ ? sourceProps.removeClippedSubviews
343
+ : convertRawProp(
344
+ context,
345
+ rawProps,
346
+ "removeClippedSubviews",
347
+ sourceProps.removeClippedSubviews,
348
+ false)) {}
349
+
350
+ #define VIEW_EVENT_CASE(eventType) \
351
+ case CONSTEXPR_RAW_PROPS_KEY_HASH("on" #eventType): { \
352
+ const auto offset = ViewEvents::Offset::eventType; \
353
+ ViewEvents defaultViewEvents{}; \
354
+ bool res = defaultViewEvents[offset]; \
355
+ if (value.hasValue()) { \
356
+ fromRawValue(context, value, res); \
357
+ } \
358
+ events[offset] = res; \
359
+ return; \
360
+ }
361
+
362
+ void BaseViewProps::setProp(
363
+ const PropsParserContext& context,
364
+ RawPropsPropNameHash hash,
365
+ const char* propName,
366
+ const RawValue& value) {
367
+ // All Props structs setProp methods must always, unconditionally,
368
+ // call all super::setProp methods, since multiple structs may
369
+ // reuse the same values.
370
+ YogaStylableProps::setProp(context, hash, propName, value);
371
+ AccessibilityProps::setProp(context, hash, propName, value);
372
+
373
+ static auto defaults = BaseViewProps{};
374
+
375
+ switch (hash) {
376
+ RAW_SET_PROP_SWITCH_CASE_BASIC(opacity);
377
+ RAW_SET_PROP_SWITCH_CASE_BASIC(backgroundColor);
378
+ RAW_SET_PROP_SWITCH_CASE(backgroundImage, "experimental_backgroundImage");
379
+ RAW_SET_PROP_SWITCH_CASE_BASIC(shadowColor);
380
+ RAW_SET_PROP_SWITCH_CASE_BASIC(shadowOffset);
381
+ RAW_SET_PROP_SWITCH_CASE_BASIC(shadowOpacity);
382
+ RAW_SET_PROP_SWITCH_CASE_BASIC(shadowRadius);
383
+ RAW_SET_PROP_SWITCH_CASE_BASIC(transform);
384
+ RAW_SET_PROP_SWITCH_CASE_BASIC(backfaceVisibility);
385
+ RAW_SET_PROP_SWITCH_CASE_BASIC(shouldRasterize);
386
+ RAW_SET_PROP_SWITCH_CASE_BASIC(zIndex);
387
+ RAW_SET_PROP_SWITCH_CASE_BASIC(pointerEvents);
388
+ RAW_SET_PROP_SWITCH_CASE_BASIC(isolation);
389
+ RAW_SET_PROP_SWITCH_CASE_BASIC(hitSlop);
390
+ RAW_SET_PROP_SWITCH_CASE_BASIC(onLayout);
391
+ RAW_SET_PROP_SWITCH_CASE_BASIC(collapsable);
392
+ RAW_SET_PROP_SWITCH_CASE_BASIC(collapsableChildren);
393
+ RAW_SET_PROP_SWITCH_CASE_BASIC(removeClippedSubviews);
394
+ RAW_SET_PROP_SWITCH_CASE_BASIC(cursor);
395
+ RAW_SET_PROP_SWITCH_CASE_BASIC(outlineColor);
396
+ RAW_SET_PROP_SWITCH_CASE_BASIC(outlineOffset);
397
+ RAW_SET_PROP_SWITCH_CASE_BASIC(outlineStyle);
398
+ RAW_SET_PROP_SWITCH_CASE_BASIC(outlineWidth);
399
+ RAW_SET_PROP_SWITCH_CASE_BASIC(filter);
400
+ RAW_SET_PROP_SWITCH_CASE_BASIC(boxShadow);
401
+ RAW_SET_PROP_SWITCH_CASE_BASIC(mixBlendMode);
402
+ // events field
403
+ VIEW_EVENT_CASE(PointerEnter);
404
+ VIEW_EVENT_CASE(PointerEnterCapture);
405
+ VIEW_EVENT_CASE(PointerMove);
406
+ VIEW_EVENT_CASE(PointerMoveCapture);
407
+ VIEW_EVENT_CASE(PointerLeave);
408
+ VIEW_EVENT_CASE(PointerLeaveCapture);
409
+ VIEW_EVENT_CASE(PointerOver);
410
+ VIEW_EVENT_CASE(PointerOverCapture);
411
+ VIEW_EVENT_CASE(PointerOut);
412
+ VIEW_EVENT_CASE(PointerOutCapture);
413
+ // [Windows
414
+ VIEW_EVENT_CASE(Click);
415
+ VIEW_EVENT_CASE(ClickCapture);
416
+ VIEW_EVENT_CASE(PointerDown);
417
+ VIEW_EVENT_CASE(PointerDownCapture);
418
+ VIEW_EVENT_CASE(PointerUp);
419
+ VIEW_EVENT_CASE(PointerUpCapture);
420
+ VIEW_EVENT_CASE(GotPointerCapture);
421
+ VIEW_EVENT_CASE(LostPointerCapture);
422
+ // Windows]
423
+ VIEW_EVENT_CASE(MoveShouldSetResponder);
424
+ VIEW_EVENT_CASE(MoveShouldSetResponderCapture);
425
+ VIEW_EVENT_CASE(StartShouldSetResponder);
426
+ VIEW_EVENT_CASE(StartShouldSetResponderCapture);
427
+ VIEW_EVENT_CASE(ResponderGrant);
428
+ VIEW_EVENT_CASE(ResponderReject);
429
+ VIEW_EVENT_CASE(ResponderStart);
430
+ VIEW_EVENT_CASE(ResponderEnd);
431
+ VIEW_EVENT_CASE(ResponderRelease);
432
+ VIEW_EVENT_CASE(ResponderMove);
433
+ VIEW_EVENT_CASE(ResponderTerminate);
434
+ VIEW_EVENT_CASE(ResponderTerminationRequest);
435
+ VIEW_EVENT_CASE(ShouldBlockNativeResponder);
436
+ VIEW_EVENT_CASE(TouchStart);
437
+ VIEW_EVENT_CASE(TouchMove);
438
+ VIEW_EVENT_CASE(TouchEnd);
439
+ VIEW_EVENT_CASE(TouchCancel);
440
+ // BorderRadii
441
+ SET_CASCADED_RECTANGLE_CORNERS(borderRadii, "border", "Radius", value);
442
+ SET_CASCADED_RECTANGLE_EDGES(borderColors, "border", "Color", value);
443
+ SET_CASCADED_RECTANGLE_EDGES(borderStyles, "border", "Style", value);
444
+ }
445
+ }
446
+
447
+ #pragma mark - Convenience Methods
448
+
449
+ static BorderRadii ensureNoOverlap(const BorderRadii& radii, const Size& size) {
450
+ // "Corner curves must not overlap: When the sum of any two adjacent border
451
+ // radii exceeds the size of the border box, UAs must proportionally reduce
452
+ // the used values of all border radii until none of them overlap."
453
+ // Source: https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
454
+
455
+ float leftEdgeRadii = radii.topLeft.vertical + radii.bottomLeft.vertical;
456
+ float topEdgeRadii = radii.topLeft.horizontal + radii.topRight.horizontal;
457
+ float rightEdgeRadii = radii.topRight.vertical + radii.bottomRight.vertical;
458
+ float bottomEdgeRadii =
459
+ radii.bottomLeft.horizontal + radii.bottomRight.horizontal;
460
+
461
+ float leftEdgeRadiiScale =
462
+ (leftEdgeRadii > 0) ? std::min(size.height / leftEdgeRadii, (Float)1) : 0;
463
+ float topEdgeRadiiScale =
464
+ (topEdgeRadii > 0) ? std::min(size.width / topEdgeRadii, (Float)1) : 0;
465
+ float rightEdgeRadiiScale = (rightEdgeRadii > 0)
466
+ ? std::min(size.height / rightEdgeRadii, (Float)1)
467
+ : 0;
468
+ float bottomEdgeRadiiScale = (bottomEdgeRadii > 0)
469
+ ? std::min(size.width / bottomEdgeRadii, (Float)1)
470
+ : 0;
471
+
472
+ return BorderRadii{
473
+ .topLeft =
474
+ {static_cast<float>(
475
+ radii.topLeft.vertical *
476
+ std::min(topEdgeRadiiScale, leftEdgeRadiiScale)),
477
+ static_cast<float>(
478
+ radii.topLeft.horizontal *
479
+ std::min(topEdgeRadiiScale, leftEdgeRadiiScale))},
480
+ .topRight =
481
+ {static_cast<float>(
482
+ radii.topRight.vertical *
483
+ std::min(topEdgeRadiiScale, rightEdgeRadiiScale)),
484
+ static_cast<float>(
485
+ radii.topRight.horizontal *
486
+ std::min(topEdgeRadiiScale, rightEdgeRadiiScale))},
487
+ .bottomLeft =
488
+ {static_cast<float>(
489
+ radii.bottomLeft.vertical *
490
+ std::min(bottomEdgeRadiiScale, leftEdgeRadiiScale)),
491
+ static_cast<float>(
492
+ radii.bottomLeft.horizontal *
493
+ std::min(bottomEdgeRadiiScale, leftEdgeRadiiScale))},
494
+ .bottomRight =
495
+ {static_cast<float>(
496
+ radii.bottomRight.vertical *
497
+ std::min(bottomEdgeRadiiScale, rightEdgeRadiiScale)),
498
+ static_cast<float>(
499
+ radii.bottomRight.horizontal *
500
+ std::min(bottomEdgeRadiiScale, rightEdgeRadiiScale))},
501
+ };
502
+ }
503
+
504
+ static BorderRadii radiiPercentToPoint(
505
+ const RectangleCorners<ValueUnit>& radii,
506
+ const Size& size) {
507
+ return BorderRadii{
508
+ .topLeft =
509
+ {radii.topLeft.resolve(size.height),
510
+ radii.topLeft.resolve(size.width)},
511
+ .topRight =
512
+ {radii.topRight.resolve(size.height),
513
+ radii.topRight.resolve(size.width)},
514
+ .bottomLeft =
515
+ {radii.bottomLeft.resolve(size.height),
516
+ radii.bottomLeft.resolve(size.width)},
517
+ .bottomRight =
518
+ {radii.bottomRight.resolve(size.height),
519
+ radii.bottomRight.resolve(size.width)},
520
+ };
521
+ }
522
+
523
+ CascadedBorderWidths BaseViewProps::getBorderWidths() const {
524
+ return CascadedBorderWidths{
525
+ .left = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Left)),
526
+ .top = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Top)),
527
+ .right = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Right)),
528
+ .bottom =
529
+ optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Bottom)),
530
+ .start = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Start)),
531
+ .end = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::End)),
532
+ .horizontal =
533
+ optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Horizontal)),
534
+ .vertical =
535
+ optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Vertical)),
536
+ .all = optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::All)),
537
+ };
538
+ }
539
+
540
+ BorderMetrics BaseViewProps::resolveBorderMetrics(
541
+ const LayoutMetrics& layoutMetrics) const {
542
+ auto isRTL =
543
+ bool{layoutMetrics.layoutDirection == LayoutDirection::RightToLeft};
544
+
545
+ auto borderWidths = getBorderWidths();
546
+
547
+ BorderRadii radii = radiiPercentToPoint(
548
+ borderRadii.resolve(isRTL, ValueUnit{0.0f, UnitType::Point}),
549
+ layoutMetrics.frame.size);
550
+
551
+ return {
552
+ .borderColors = borderColors.resolve(isRTL, {}),
553
+ .borderWidths = borderWidths.resolve(isRTL, 0),
554
+ .borderRadii = ensureNoOverlap(radii, layoutMetrics.frame.size),
555
+ .borderCurves = borderCurves.resolve(isRTL, BorderCurve::Circular),
556
+ .borderStyles = borderStyles.resolve(isRTL, BorderStyle::Solid),
557
+ };
558
+ }
559
+
560
+ Transform BaseViewProps::resolveTransform(
561
+ const LayoutMetrics& layoutMetrics) const {
562
+ const auto& frameSize = layoutMetrics.frame.size;
563
+ return resolveTransform(frameSize, transform, transformOrigin);
564
+ }
565
+
566
+ Transform BaseViewProps::resolveTransform(
567
+ const Size& frameSize,
568
+ const Transform& transform,
569
+ const TransformOrigin& transformOrigin) {
570
+ auto transformMatrix = Transform{};
571
+
572
+ // transform is matrix
573
+ if (transform.operations.size() == 1 &&
574
+ transform.operations[0].type == TransformOperationType::Arbitrary) {
575
+ transformMatrix = transform;
576
+ } else {
577
+ for (const auto& operation : transform.operations) {
578
+ transformMatrix = transformMatrix *
579
+ Transform::FromTransformOperation(operation, frameSize, transform);
580
+ }
581
+ }
582
+
583
+ if (transformOrigin.isSet()) {
584
+ std::array<float, 3> translateOffsets = getTranslateForTransformOrigin(
585
+ frameSize.width, frameSize.height, transformOrigin);
586
+ transformMatrix =
587
+ Transform::Translate(
588
+ translateOffsets[0], translateOffsets[1], translateOffsets[2]) *
589
+ transformMatrix *
590
+ Transform::Translate(
591
+ -translateOffsets[0], -translateOffsets[1], -translateOffsets[2]);
592
+ }
593
+
594
+ return transformMatrix;
595
+ }
596
+
597
+ bool BaseViewProps::getClipsContentToBounds() const {
598
+ return yogaStyle.overflow() != yoga::Overflow::Visible;
599
+ }
600
+
601
+ #pragma mark - DebugStringConvertible
602
+
603
+ #if RN_DEBUG_STRING_CONVERTIBLE
604
+ SharedDebugStringConvertibleList BaseViewProps::getDebugProps() const {
605
+ const auto& defaultBaseViewProps = BaseViewProps();
606
+
607
+ return AccessibilityProps::getDebugProps() +
608
+ YogaStylableProps::getDebugProps() +
609
+ SharedDebugStringConvertibleList{
610
+ debugStringConvertibleItem(
611
+ "opacity", opacity, defaultBaseViewProps.opacity),
612
+ debugStringConvertibleItem(
613
+ "backgroundColor",
614
+ backgroundColor,
615
+ defaultBaseViewProps.backgroundColor),
616
+ debugStringConvertibleItem(
617
+ "zIndex", zIndex, defaultBaseViewProps.zIndex.value_or(0)),
618
+ debugStringConvertibleItem(
619
+ "pointerEvents",
620
+ pointerEvents,
621
+ defaultBaseViewProps.pointerEvents),
622
+ debugStringConvertibleItem(
623
+ "transform", transform, defaultBaseViewProps.transform),
624
+ };
625
+ }
626
+ #endif
627
+
628
+ } // namespace facebook::react
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-windows",
3
- "version": "0.81.9",
3
+ "version": "0.81.11",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",