react-native-windows 0.74.4 → 0.74.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/Libraries/Components/TextInput/TextInput.windows.js +6 -2
  2. package/Libraries/Components/View/View.windows.js +3 -0
  3. package/Microsoft.ReactNative/ComponentView.idl +26 -0
  4. package/Microsoft.ReactNative/CompositionComponentView.idl +19 -7
  5. package/Microsoft.ReactNative/CompositionRootView.idl +1 -0
  6. package/Microsoft.ReactNative/CompositionUIService.idl +4 -0
  7. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.cpp +2 -1
  8. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +106 -19
  9. package/Microsoft.ReactNative/Fabric/AbiViewProps.h +45 -13
  10. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +83 -12
  11. package/Microsoft.ReactNative/Fabric/ComponentView.h +33 -2
  12. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.cpp +28 -64
  13. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.h +7 -11
  14. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.cpp +30 -11
  15. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.h +4 -0
  16. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootView_emptyimpl.cpp +4 -0
  17. package/Microsoft.ReactNative/Fabric/Composition/CompositionUIService.cpp +12 -0
  18. package/Microsoft.ReactNative/Fabric/Composition/CompositionUIService.h +4 -0
  19. package/Microsoft.ReactNative/Fabric/Composition/CompositionUIService_emptyimpl.cpp +6 -0
  20. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +60 -39
  21. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +19 -6
  22. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +1 -0
  23. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +152 -0
  24. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +85 -0
  25. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.cpp +49 -95
  26. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.h +11 -15
  27. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +16 -31
  28. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +5 -8
  29. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +24 -81
  30. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.h +4 -13
  31. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +41 -40
  32. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +5 -1
  33. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +53 -68
  34. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +5 -7
  35. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +38 -84
  36. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h +6 -10
  37. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +59 -109
  38. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +9 -15
  39. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -0
  40. package/Microsoft.ReactNative/FocusManager.idl +22 -0
  41. package/Microsoft.ReactNative/ViewProps.idl +37 -3
  42. package/Microsoft.ReactNative.Cxx/JSValueComposition.h +4 -0
  43. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  44. package/Shared/Shared.vcxitems +6 -0
  45. package/package.json +1 -1
@@ -23,14 +23,13 @@ WindowsModalHostComponentView::WindowsModalHostComponentView(
23
23
  facebook::react::Tag tag,
24
24
  winrt::Microsoft::ReactNative::ReactContext const &reactContext)
25
25
  : Super(
26
+ WindowsModalHostComponentView::defaultProps(),
26
27
  compContext,
27
28
  tag,
28
29
  reactContext,
29
30
  ComponentViewFeatures::Default & ~ComponentViewFeatures::Background,
30
31
  false) {
31
- m_props = std::make_shared<facebook::react::ModalHostViewProps const>();
32
32
  m_context = reactContext; // save context
33
- m_visual = compContext.CreateSpriteVisual();
34
33
  }
35
34
 
36
35
  winrt::Microsoft::ReactNative::ComponentView WindowsModalHostComponentView::Create(
@@ -201,7 +200,8 @@ void WindowsModalHostComponentView::HandleCommand(
201
200
  void WindowsModalHostComponentView::updateProps(
202
201
  facebook::react::Props::Shared const &props,
203
202
  facebook::react::Props::Shared const &oldProps) noexcept {
204
- const auto &oldModalProps = *std::static_pointer_cast<const facebook::react::ModalHostViewProps>(m_props);
203
+ const auto &oldModalProps =
204
+ *std::static_pointer_cast<const facebook::react::ModalHostViewProps>(oldProps ? oldProps : viewProps());
205
205
  const auto &newModalProps = *std::static_pointer_cast<const facebook::react::ModalHostViewProps>(props);
206
206
 
207
207
  // currently Modal only gets Destroyed by closing the window
@@ -210,20 +210,15 @@ void WindowsModalHostComponentView::updateProps(
210
210
  ShowOnUIThread();
211
211
  }
212
212
 
213
- // update BaseComponentView props
214
- updateTransformProps(oldModalProps, newModalProps, m_visual);
215
- Super::updateProps(props, oldProps);
216
- m_props = std::static_pointer_cast<facebook::react::ModalHostViewProps const>(props);
213
+ base_type::updateProps(props, oldProps);
217
214
  }
218
215
 
219
216
  void WindowsModalHostComponentView::updateLayoutMetrics(
220
217
  facebook::react::LayoutMetrics const &layoutMetrics,
221
218
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept {
222
- if ((layoutMetrics.displayType != m_layoutMetrics.displayType)) {
223
- OuterVisual().IsVisible(layoutMetrics.displayType != facebook::react::DisplayType::None);
224
- }
219
+ Super::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
225
220
 
226
- // Temparary placeholder for Modal, draws on main hwnd
221
+ // Temporary placeholder for Modal, draws on main hwnd
227
222
  if (m_layoutMetrics.frame.size != layoutMetrics.frame.size ||
228
223
  m_layoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor || m_layoutMetrics.frame.size.width == 0) {
229
224
  // Always make visual a min size, so that even if its laid out at zero size, its clear an unimplemented view was
@@ -241,9 +236,9 @@ void WindowsModalHostComponentView::updateLayoutMetrics(
241
236
  drawingSurface.HorizontalAlignmentRatio(0.f);
242
237
  drawingSurface.VerticalAlignmentRatio(0.f);
243
238
  drawingSurface.Stretch(winrt::Microsoft::ReactNative::Composition::Experimental::CompositionStretch::None);
244
- m_visual.Brush(drawingSurface);
245
- m_visual.Size(surfaceSize);
246
- m_visual.Offset({
239
+ Visual().as<Experimental::ISpriteVisual>().Brush(drawingSurface);
240
+ Visual().Size(surfaceSize);
241
+ Visual().Offset({
247
242
  layoutMetrics.frame.origin.x * layoutMetrics.pointScaleFactor,
248
243
  layoutMetrics.frame.origin.y * layoutMetrics.pointScaleFactor,
249
244
  0.0f,
@@ -290,28 +285,18 @@ void WindowsModalHostComponentView::updateLayoutMetrics(
290
285
  }
291
286
  }
292
287
  }
293
-
294
- Super::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
295
288
  }
296
289
 
297
290
  void WindowsModalHostComponentView::updateState(
298
291
  facebook::react::State::Shared const &state,
299
292
  facebook::react::State::Shared const &oldState) noexcept {}
300
293
 
301
- void WindowsModalHostComponentView::prepareForRecycle() noexcept {}
302
-
303
- facebook::react::SharedViewProps WindowsModalHostComponentView::viewProps() noexcept {
304
- return m_props;
305
- }
306
-
307
- winrt::Microsoft::ReactNative::Composition::Experimental::IVisual WindowsModalHostComponentView::Visual()
308
- const noexcept {
309
- return m_visual;
294
+ facebook::react::SharedViewProps WindowsModalHostComponentView::defaultProps() noexcept {
295
+ static auto const defaultProps = std::make_shared<facebook::react::ModalHostViewProps const>();
296
+ return defaultProps;
310
297
  }
311
-
312
- winrt::Microsoft::ReactNative::Composition::Experimental::IVisual WindowsModalHostComponentView::OuterVisual()
313
- const noexcept {
314
- return m_visual;
298
+ const facebook::react::ModalHostViewProps &WindowsModalHostComponentView::modalHostViewProps() const noexcept {
299
+ return *std::static_pointer_cast<const facebook::react::ModalHostViewProps>(viewProps());
315
300
  }
316
301
 
317
302
  facebook::react::Tag WindowsModalHostComponentView::hitTest(
@@ -320,8 +305,8 @@ facebook::react::Tag WindowsModalHostComponentView::hitTest(
320
305
  bool ignorePointerEvents) const noexcept {
321
306
  facebook::react::Point ptLocal{pt.x - m_layoutMetrics.frame.origin.x, pt.y - m_layoutMetrics.frame.origin.y};
322
307
 
323
- if ((ignorePointerEvents || m_props->pointerEvents == facebook::react::PointerEventsMode::Auto ||
324
- m_props->pointerEvents == facebook::react::PointerEventsMode::BoxOnly) &&
308
+ if ((ignorePointerEvents || viewProps()->pointerEvents == facebook::react::PointerEventsMode::Auto ||
309
+ viewProps()->pointerEvents == facebook::react::PointerEventsMode::BoxOnly) &&
325
310
  ptLocal.x >= 0 && ptLocal.x <= m_layoutMetrics.frame.size.width && ptLocal.y >= 0 &&
326
311
  ptLocal.y <= m_layoutMetrics.frame.size.height) {
327
312
  localPt = ptLocal;
@@ -13,8 +13,9 @@
13
13
 
14
14
  namespace winrt::Microsoft::ReactNative::Composition::implementation {
15
15
 
16
- struct WindowsModalHostComponentView : WindowsModalHostComponentViewT<WindowsModalHostComponentView, ComponentView> {
17
- using Super = WindowsModalHostComponentViewT<WindowsModalHostComponentView, ComponentView>;
16
+ struct WindowsModalHostComponentView
17
+ : WindowsModalHostComponentViewT<WindowsModalHostComponentView, ViewComponentView> {
18
+ using Super = WindowsModalHostComponentViewT<WindowsModalHostComponentView, ViewComponentView>;
18
19
 
19
20
  [[nodiscard]] static winrt::Microsoft::ReactNative::ComponentView Create(
20
21
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
@@ -37,13 +38,11 @@ struct WindowsModalHostComponentView : WindowsModalHostComponentViewT<WindowsMod
37
38
  void updateLayoutMetrics(
38
39
  facebook::react::LayoutMetrics const &layoutMetrics,
39
40
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
40
- void prepareForRecycle() noexcept override;
41
- facebook::react::SharedViewProps viewProps() noexcept override;
41
+ static facebook::react::SharedViewProps defaultProps() noexcept;
42
+ const facebook::react::ModalHostViewProps &modalHostViewProps() const noexcept;
42
43
  bool focusable() const noexcept override;
43
44
  facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents)
44
45
  const noexcept override;
45
- winrt::Microsoft::ReactNative::Composition::Experimental::IVisual Visual() const noexcept override;
46
- winrt::Microsoft::ReactNative::Composition::Experimental::IVisual OuterVisual() const noexcept override;
47
46
  virtual std::string DefaultControlType() const noexcept;
48
47
 
49
48
  WindowsModalHostComponentView(
@@ -58,8 +57,6 @@ struct WindowsModalHostComponentView : WindowsModalHostComponentViewT<WindowsMod
58
57
  static void RegisterWndClass() noexcept;
59
58
 
60
59
  private:
61
- std::shared_ptr<facebook::react::ModalHostViewProps const> m_props;
62
- winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual m_visual{nullptr};
63
60
  HWND m_hwnd{nullptr};
64
61
  winrt::Microsoft::ReactNative::ReactContext m_context;
65
62
  };
@@ -23,14 +23,12 @@ ParagraphComponentView::ParagraphComponentView(
23
23
  facebook::react::Tag tag,
24
24
  winrt::Microsoft::ReactNative::ReactContext const &reactContext)
25
25
  : Super(
26
+ ParagraphComponentView::defaultProps(),
26
27
  compContext,
27
28
  tag,
28
29
  reactContext,
29
30
  ComponentViewFeatures::Default & ~ComponentViewFeatures::Background,
30
- false) {
31
- static auto const defaultProps = std::make_shared<facebook::react::ParagraphProps const>();
32
- m_props = defaultProps;
33
- }
31
+ false) {}
34
32
 
35
33
  void ParagraphComponentView::MountChildComponentView(
36
34
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
@@ -49,7 +47,8 @@ void ParagraphComponentView::UnmountChildComponentView(
49
47
  void ParagraphComponentView::updateProps(
50
48
  facebook::react::Props::Shared const &props,
51
49
  facebook::react::Props::Shared const &oldProps) noexcept {
52
- const auto &oldViewProps = *std::static_pointer_cast<const facebook::react::ParagraphProps>(m_props);
50
+ const auto &oldViewProps =
51
+ *std::static_pointer_cast<const facebook::react::ParagraphProps>(oldProps ? oldProps : viewProps());
53
52
  const auto &newViewProps = *std::static_pointer_cast<const facebook::react::ParagraphProps>(props);
54
53
 
55
54
  ensureVisual();
@@ -57,23 +56,16 @@ void ParagraphComponentView::updateProps(
57
56
  if (oldViewProps.textAttributes.foregroundColor != newViewProps.textAttributes.foregroundColor) {
58
57
  m_requireRedraw = true;
59
58
  }
59
+
60
60
  if (oldViewProps.textAttributes.opacity != newViewProps.textAttributes.opacity) {
61
61
  m_requireRedraw = true;
62
62
  }
63
- if (oldViewProps.testId != newViewProps.testId) {
64
- m_visual.Comment(winrt::to_hstring(newViewProps.testId));
65
- }
66
63
 
67
64
  if (oldViewProps.textAttributes.alignment != newViewProps.textAttributes.alignment) {
68
65
  updateTextAlignment(newViewProps.textAttributes.alignment);
69
66
  }
70
67
 
71
- // update BaseComponentView props
72
- updateAccessibilityProps(oldViewProps, newViewProps);
73
- updateTransformProps(oldViewProps, newViewProps, m_visual);
74
68
  Super::updateProps(props, oldProps);
75
-
76
- m_props = std::static_pointer_cast<facebook::react::ParagraphProps const>(props);
77
69
  }
78
70
 
79
71
  void ParagraphComponentView::updateEventEmitter(facebook::react::EventEmitter::Shared const &eventEmitter) noexcept {
@@ -90,60 +82,13 @@ void ParagraphComponentView::updateState(
90
82
 
91
83
  m_textLayout = nullptr;
92
84
  }
93
- void ParagraphComponentView::updateLayoutMetrics(
94
- facebook::react::LayoutMetrics const &layoutMetrics,
95
- facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept {
96
- // Set Position & Size Properties
97
-
98
- if ((layoutMetrics.displayType != m_layoutMetrics.displayType)) {
99
- OuterVisual().IsVisible(layoutMetrics.displayType != facebook::react::DisplayType::None);
100
- }
101
85
 
102
- Super::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
103
- m_visual.Size(
104
- {layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor,
105
- layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor});
106
- }
107
86
  void ParagraphComponentView::FinalizeUpdates(
108
87
  winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept {
109
88
  ensureVisual();
110
89
  updateVisualBrush();
111
90
  Super::FinalizeUpdates(updateMask);
112
91
  }
113
- void ParagraphComponentView::prepareForRecycle() noexcept {}
114
-
115
- facebook::react::SharedViewProps ParagraphComponentView::viewProps() noexcept {
116
- return m_props;
117
- }
118
-
119
- facebook::react::Tag ParagraphComponentView::hitTest(
120
- facebook::react::Point pt,
121
- facebook::react::Point &localPt,
122
- bool ignorePointerEvents) const noexcept {
123
- facebook::react::Point ptLocal{pt.x - m_layoutMetrics.frame.origin.x, pt.y - m_layoutMetrics.frame.origin.y};
124
-
125
- facebook::react::Tag targetTag;
126
-
127
- /*
128
- if ((m_props.pointerEvents == facebook::react::PointerEventsMode::Auto ||
129
- m_props.pointerEvents == facebook::react::PointerEventsMode::BoxNone) && std::any_of(m_children.rbegin(),
130
- m_children.rend(), [&targetTag, &ptLocal, &localPt](auto child) { targetTag = static_cast<const
131
- ComponentView
132
- *>(child)->hitTest(ptLocal, localPt); return targetTag != -1;
133
- }))
134
- return targetTag;
135
- */
136
-
137
- if ((ignorePointerEvents || m_props->pointerEvents == facebook::react::PointerEventsMode::Auto ||
138
- m_props->pointerEvents == facebook::react::PointerEventsMode::BoxOnly) &&
139
- ptLocal.x >= 0 && ptLocal.x <= m_layoutMetrics.frame.size.width && ptLocal.y >= 0 &&
140
- ptLocal.y <= m_layoutMetrics.frame.size.height) {
141
- localPt = ptLocal;
142
- return Tag();
143
- }
144
-
145
- return -1;
146
- }
147
92
 
148
93
  facebook::react::SharedViewEventEmitter ParagraphComponentView::eventEmitterAtPoint(
149
94
  facebook::react::Point pt) noexcept {
@@ -168,13 +113,6 @@ facebook::react::SharedViewEventEmitter ParagraphComponentView::eventEmitterAtPo
168
113
  return m_eventEmitter;
169
114
  }
170
115
 
171
- void ParagraphComponentView::ensureVisual() noexcept {
172
- if (!m_visual) {
173
- m_visual = m_compContext.CreateSpriteVisual();
174
- OuterVisual().InsertAt(m_visual, 0);
175
- }
176
- }
177
-
178
116
  void ParagraphComponentView::updateTextAlignment(
179
117
  const std::optional<facebook::react::TextAlignment> &fbAlignment) noexcept {
180
118
  m_textLayout = nullptr;
@@ -255,11 +193,11 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
255
193
 
256
194
  // The surfaceBrush's size is based on the size the text takes up, which maybe smaller than the total visual
257
195
  // So we need to align the brush within the visual to match the text alignment.
258
- const auto &paragraphProps = *std::static_pointer_cast<const facebook::react::ParagraphProps>(m_props);
259
196
  float horizAlignment{0.f};
260
197
  /*
261
- if (paragraphProps.textAttributes.alignment) {
262
- switch (*paragraphProps.textAttributes.alignment) {
198
+ const auto &props = paragraphProps()
199
+ if (props.textAttributes.alignment) {
200
+ switch (*props.textAttributes.alignment) {
263
201
  case facebook::react::TextAlignment::Center:
264
202
  horizAlignment = 0.5f;
265
203
  break;
@@ -287,7 +225,7 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
287
225
  m_drawingSurface.VerticalAlignmentRatio(0.f);
288
226
  m_drawingSurface.Stretch(winrt::Microsoft::ReactNative::Composition::Experimental::CompositionStretch::None);
289
227
  }
290
- m_visual.Brush(m_drawingSurface);
228
+ Visual().as<Experimental::ISpriteVisual>().Brush(m_drawingSurface);
291
229
  }
292
230
 
293
231
  if (m_requireRedraw) {
@@ -295,6 +233,15 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
295
233
  }
296
234
  }
297
235
 
236
+ facebook::react::SharedViewProps ParagraphComponentView::defaultProps() noexcept {
237
+ static auto const defaultProps = std::make_shared<facebook::react::ParagraphProps const>();
238
+ return defaultProps;
239
+ }
240
+
241
+ const facebook::react::ParagraphProps &ParagraphComponentView::paragraphProps() const noexcept {
242
+ return *std::static_pointer_cast<const facebook::react::ParagraphProps>(viewProps());
243
+ }
244
+
298
245
  void ParagraphComponentView::onThemeChanged() noexcept {
299
246
  DrawText();
300
247
  Super::onThemeChanged();
@@ -316,23 +263,23 @@ void ParagraphComponentView::DrawText() noexcept {
316
263
  m_drawingSurface, m_layoutMetrics.pointScaleFactor, &offset);
317
264
  if (auto d2dDeviceContext = autoDraw.GetRenderTarget()) {
318
265
  d2dDeviceContext->Clear(
319
- m_props->backgroundColor ? theme()->D2DColor(*m_props->backgroundColor)
320
- : D2D1::ColorF(D2D1::ColorF::Black, 0.0f));
266
+ viewProps()->backgroundColor ? theme()->D2DColor(*viewProps()->backgroundColor)
267
+ : D2D1::ColorF(D2D1::ColorF::Black, 0.0f));
321
268
 
322
- const auto &paragraphProps = *std::static_pointer_cast<const facebook::react::ParagraphProps>(m_props);
269
+ const auto &props = paragraphProps();
323
270
 
324
271
  RenderText(
325
272
  *d2dDeviceContext,
326
273
  *m_textLayout,
327
274
  m_attributedStringBox.getValue(),
328
- paragraphProps.textAttributes,
275
+ props.textAttributes,
329
276
  {static_cast<float>(offset.x) + m_layoutMetrics.contentInsets.left,
330
277
  static_cast<float>(offset.y) + m_layoutMetrics.contentInsets.top},
331
278
  m_layoutMetrics.pointScaleFactor,
332
279
  *theme());
333
280
 
334
- if (!isnan(paragraphProps.opacity)) {
335
- m_visual.Opacity(paragraphProps.opacity);
281
+ if (!isnan(props.opacity)) {
282
+ Visual().Opacity(props.opacity);
336
283
  }
337
284
  }
338
285
  m_requireRedraw = false;
@@ -347,10 +294,6 @@ std::string ParagraphComponentView::DefaultAccessibleName() const noexcept {
347
294
  return m_attributedStringBox.getValue().getString();
348
295
  }
349
296
 
350
- winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ParagraphComponentView::Visual() const noexcept {
351
- return m_visual;
352
- }
353
-
354
297
  winrt::Microsoft::ReactNative::ComponentView ParagraphComponentView::Create(
355
298
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
356
299
  facebook::react::Tag tag,
@@ -17,8 +17,8 @@
17
17
 
18
18
  namespace winrt::Microsoft::ReactNative::Composition::implementation {
19
19
 
20
- struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView, ComponentView> {
21
- using Super = ParagraphComponentViewT<ParagraphComponentView, ComponentView>;
20
+ struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView, ViewComponentView> {
21
+ using Super = ParagraphComponentViewT<ParagraphComponentView, ViewComponentView>;
22
22
 
23
23
  [[nodiscard]] static winrt::Microsoft::ReactNative::ComponentView Create(
24
24
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
@@ -36,21 +36,15 @@ struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView,
36
36
  void updateEventEmitter(facebook::react::EventEmitter::Shared const &eventEmitter) noexcept override;
37
37
  void updateState(facebook::react::State::Shared const &state, facebook::react::State::Shared const &oldState) noexcept
38
38
  override;
39
- void updateLayoutMetrics(
40
- facebook::react::LayoutMetrics const &layoutMetrics,
41
- facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
42
39
  void FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept override;
43
- void prepareForRecycle() noexcept override;
44
- facebook::react::SharedViewProps viewProps() noexcept override;
45
- facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents)
46
- const noexcept override;
47
40
  void OnRenderingDeviceLost() noexcept override;
48
41
  void onThemeChanged() noexcept override;
49
42
  facebook::react::SharedViewEventEmitter eventEmitterAtPoint(facebook::react::Point pt) noexcept override;
50
43
 
51
- winrt::Microsoft::ReactNative::Composition::Experimental::IVisual Visual() const noexcept override;
52
44
  virtual std::string DefaultControlType() const noexcept override;
53
45
  virtual std::string DefaultAccessibleName() const noexcept override;
46
+ static facebook::react::SharedViewProps defaultProps() noexcept;
47
+ const facebook::react::ParagraphProps &paragraphProps() const noexcept;
54
48
 
55
49
  ParagraphComponentView(
56
50
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
@@ -58,13 +52,10 @@ struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView,
58
52
  winrt::Microsoft::ReactNative::ReactContext const &reactContext);
59
53
 
60
54
  private:
61
- void ensureVisual() noexcept;
62
55
  void updateVisualBrush() noexcept;
63
56
  void DrawText() noexcept;
64
57
  void updateTextAlignment(const std::optional<facebook::react::TextAlignment> &fbAlignment) noexcept;
65
58
 
66
- std::shared_ptr<facebook::react::ParagraphProps const> m_props;
67
- winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual m_visual{nullptr};
68
59
  winrt::com_ptr<::IDWriteTextLayout> m_textLayout;
69
60
  facebook::react::AttributedStringBox m_attributedStringBox;
70
61
  facebook::react::ParagraphAttributes m_paragraphAttributes;
@@ -18,6 +18,7 @@ RootComponentView::RootComponentView(
18
18
  facebook::react::Tag tag,
19
19
  winrt::Microsoft::ReactNative::ReactContext const &reactContext)
20
20
  : base_type(
21
+ {}, // default viewProps
21
22
  compContext,
22
23
  tag,
23
24
  reactContext,
@@ -44,7 +45,7 @@ RootComponentView *RootComponentView::rootComponentView() noexcept {
44
45
  return this;
45
46
  }
46
47
 
47
- winrt::Microsoft::ReactNative::ComponentView &RootComponentView::GetFocusedComponent() noexcept {
48
+ winrt::Microsoft::ReactNative::ComponentView RootComponentView::GetFocusedComponent() noexcept {
48
49
  return m_focusedComponent;
49
50
  }
50
51
  void RootComponentView::SetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &value) noexcept {
@@ -52,69 +53,69 @@ void RootComponentView::SetFocusedComponent(const winrt::Microsoft::ReactNative:
52
53
  return;
53
54
 
54
55
  if (m_focusedComponent) {
55
- winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_focusedComponent)->onFocusLost();
56
+ auto args = winrt::make<winrt::Microsoft::ReactNative::implementation::LostFocusEventArgs>(m_focusedComponent);
57
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_focusedComponent)
58
+ ->onLostFocus(args);
56
59
  }
57
60
 
58
61
  if (value) {
59
62
  if (auto rootView = m_wkRootView.get()) {
60
63
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::CompositionRootView>(rootView)->TrySetFocus();
61
64
  }
62
- winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(value)->onFocusGained();
65
+ auto args = winrt::make<winrt::Microsoft::ReactNative::implementation::GotFocusEventArgs>(value);
66
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(value)->onGotFocus(args);
63
67
  }
64
68
 
65
69
  m_focusedComponent = value;
66
70
  }
67
71
 
68
- winrt::Microsoft::ReactNative::implementation::ComponentView *NavigateFocusHelper(
69
- winrt::Microsoft::ReactNative::implementation::ComponentView &view,
70
- winrt::Microsoft::ReactNative::FocusNavigationReason reason) {
71
- if (reason == winrt::Microsoft::ReactNative::FocusNavigationReason::First) {
72
- if (view.focusable()) {
73
- return &view;
74
- }
75
- }
76
- winrt::Microsoft::ReactNative::implementation::ComponentView *toFocus = nullptr;
77
-
78
- Mso::Functor<bool(::winrt::Microsoft::ReactNative::implementation::ComponentView & v)> fn =
79
- [reason, &toFocus](::winrt::Microsoft::ReactNative::implementation::ComponentView &v) noexcept
80
- -> bool { return (toFocus = NavigateFocusHelper(v, reason)); };
81
-
82
- if (view.runOnChildren(reason == winrt::Microsoft::ReactNative::FocusNavigationReason::First, fn)) {
83
- return toFocus;
84
- }
85
-
86
- if (reason == winrt::Microsoft::ReactNative::FocusNavigationReason::Last) {
87
- if (view.focusable()) {
88
- return &view;
89
- }
90
- }
91
-
92
- return nullptr;
93
- }
94
-
95
72
  bool RootComponentView::NavigateFocus(const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept {
96
73
  if (request.Reason() == winrt::Microsoft::ReactNative::FocusNavigationReason::Restore) {
97
74
  // No-op for now
98
75
  return m_focusedComponent != nullptr;
99
76
  }
100
77
 
101
- auto view = NavigateFocusHelper(*this, request.Reason());
78
+ auto view = (request.Reason() == winrt::Microsoft::ReactNative::FocusNavigationReason::First)
79
+ ? FocusManager::FindFirstFocusableElement(*this)
80
+ : FocusManager::FindLastFocusableElement(*this);
102
81
  if (view) {
103
- winrt::Microsoft::ReactNative::ComponentView component{nullptr};
104
- winrt::check_hresult(view->QueryInterface(
105
- winrt::guid_of<winrt::Microsoft::ReactNative::ComponentView>(), winrt::put_abi(component)));
106
- SetFocusedComponent(component);
82
+ TrySetFocusedComponent(view);
107
83
  }
108
84
  return view != nullptr;
109
85
  }
110
86
 
111
87
  bool RootComponentView::TrySetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
112
- auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view);
113
- if (selfView->focusable()) {
114
- selfView->rootComponentView()->SetFocusedComponent(view);
115
- return true;
88
+ auto target = view;
89
+ auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
90
+ if (selfView && !selfView->focusable()) {
91
+ target = FocusManager::FindFirstFocusableElement(target);
92
+ if (!target)
93
+ return false;
94
+ selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
95
+ }
96
+
97
+ if (selfView && selfView->rootComponentView() != this)
98
+ return false;
99
+
100
+ auto losingFocusArgs = winrt::make<winrt::Microsoft::ReactNative::implementation::LosingFocusEventArgs>(
101
+ target, m_focusedComponent, target);
102
+ if (m_focusedComponent) {
103
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_focusedComponent)
104
+ ->onLosingFocus(losingFocusArgs);
116
105
  }
117
- return false;
106
+
107
+ if (losingFocusArgs.NewFocusedComponent()) {
108
+ auto gettingFocusArgs = winrt::make<winrt::Microsoft::ReactNative::implementation::GettingFocusEventArgs>(
109
+ target, m_focusedComponent, losingFocusArgs.NewFocusedComponent());
110
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(losingFocusArgs.NewFocusedComponent())
111
+ ->onGettingFocus(gettingFocusArgs);
112
+
113
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(losingFocusArgs.NewFocusedComponent())
114
+ ->rootComponentView()
115
+ ->SetFocusedComponent(gettingFocusArgs.NewFocusedComponent());
116
+ }
117
+
118
+ return true;
118
119
  }
119
120
 
120
121
  bool RootComponentView::TryMoveFocus(bool next) noexcept {
@@ -8,6 +8,7 @@
8
8
  #include <Microsoft.ReactNative.Cxx/ReactContext.h>
9
9
 
10
10
  #include "CompositionViewComponentView.h"
11
+ #include "FocusManager.h"
11
12
  #include "Theme.h"
12
13
 
13
14
  #include "Composition.RootComponentView.g.h"
@@ -25,7 +26,7 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
25
26
  facebook::react::Tag tag,
26
27
  winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept;
27
28
 
28
- winrt::Microsoft::ReactNative::ComponentView &GetFocusedComponent() noexcept;
29
+ winrt::Microsoft::ReactNative::ComponentView GetFocusedComponent() noexcept;
29
30
  void SetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &value) noexcept;
30
31
  bool TrySetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept;
31
32
 
@@ -51,6 +52,9 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
51
52
 
52
53
  virtual ~RootComponentView();
53
54
 
55
+ winrt::Microsoft::ReactNative::ComponentView FindFirstFocusableElement() noexcept;
56
+ winrt::Microsoft::ReactNative::ComponentView FindLastFocusableElement() noexcept;
57
+
54
58
  private:
55
59
  // should this be a ReactTaggedView? - It shouldn't actually matter since if the view is going away it should always
56
60
  // be clearing its focus But being a reactTaggedView might make it easier to identify cases where that isn't