Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
5b3d71c
[fabric] Support selection of Paragraph component text content
Sep 20, 2023
529930e
[fabric] Fix onPress not working for Text
Oct 9, 2023
5f134a9
[fabric] Add native focus props to ViewComponentView
shwanton Oct 6, 2023
f5278be
[fabric] Don't flatten View if focusable or enableFocusRing
shwanton Oct 9, 2023
9addf74
[fabric] Add iterator to SurfaceTelemetry.cpp
8Keep Nov 9, 2023
c55fb33
[fabric] Selection range should use the correct backed input range
shwanton Nov 2, 2023
1ff3069
[fabric][a11y] Make text render with static text role
Dec 1, 2023
9bd1ab4
[fabric] Add wrapper class for TextView with scroll callback support
Dec 7, 2023
653c34e
[fabric] Add responder property to backing text input view protocol
Dec 7, 2023
2650c61
[fabric] Update backed text input copy method to support view instances
Dec 7, 2023
689b3cb
[fabric] Use wrapped text view for multiline TextInput
Dec 7, 2023
3f9c1d5
[fabric] Support showing/hiding the focus ring for TextInput
Dec 9, 2023
a40aecd
[fabric] Implement escape/cancel key press callback for TextInput
Dec 9, 2023
607c660
[fabric] Submit scroll view metrics when scrolling multiline TextInput
Dec 9, 2023
92ad521
[fabric] Fix random TextInput cursor position changes while typing
Jan 15, 2024
66c6596
[fabric] Add submitKeyEvents property to TextInput
Jan 18, 2024
ca210b3
[fabric] Implement TextInput key down event checking for submit
Jan 18, 2024
1652d20
[fabric] Add support for clearing the TextInput on submit
Jan 18, 2024
f48f566
[fabric] Add support for the secure text entry to TextInput
Jan 19, 2024
f8c2f57
[fabric] Copy accessibility attributes when switching TextInput backi…
Jan 19, 2024
f0277f5
[fabric] Add HostPlatformViewProps to ViewProps
Jan 29, 2024
4585d7b
[fabric] Add HostPlatformViewEventEmitter to ViewEventEmitter
Jan 29, 2024
6fe9604
[fabric] Move focus props to HostPlatformViewProps
Jan 29, 2024
3eb2766
[fabric] Add valid key down/up props to View
Jan 30, 2024
b7c1dc8
[fabric] Add key down/up event emitters to View
Jan 30, 2024
9340c6f
[fabric] Add key down/up handling to View component
Jan 30, 2024
6fae948
[fabric] Add keyboard event handling to TextInput component
Jan 30, 2024
8bd960c
[fabric] Fix missing includes for windows build
Jan 30, 2024
4e68979
[fabric] Add mouse event props to View
Feb 7, 2024
c29a062
[fabric] Add mouse enter/leave tracking to the View component
Feb 7, 2024
121921c
[fabric] Disable view flattening for views using mouse events
Feb 7, 2024
f3287c2
[fabric] Add mouse enter/leave tracking on scroll
Feb 7, 2024
da355fa
[fabric] Check for assigned event emitter before sending key/mouse ev…
Feb 8, 2024
b682b46
[fabric] Add draggedTypes prop to View
Feb 12, 2024
995a6b4
[fabric] Add drag and drop event emitters to View
Feb 12, 2024
6b39bc4
[fabric] Add drag and drop support to View component
Feb 12, 2024
242ce21
[fabric] Add drag and drop support to TextInput component
Feb 12, 2024
1f40bde
[fabric] Limit draggedTypes prop values to supported options
Feb 13, 2024
38c9690
[fabric] Add file paste event emitter to TextInput component
Feb 13, 2024
06f5346
[fabric] Add file paste support to TextInput component
Feb 13, 2024
a863682
[fabric] Fix missing method declaration of View component
Feb 13, 2024
06904fa
[fabric] Fix namespace in View component header
Feb 13, 2024
4e74505
[fabric] Fix crash on key up in non focusable view
Feb 20, 2024
391c4ca
[fabric] Add missing pragma marks in macOS view event emitter
Feb 20, 2024
56f4dce
[fabric] Add focus/blur event emitters to View
Feb 20, 2024
e49e103
[fabric] Add View focus/blur event emitting on first responder change
Feb 20, 2024
90f30a1
[fabric] Add double click event prop to View component
Feb 21, 2024
b8bacdc
[fabric] Add double click support to View component
Feb 21, 2024
a9a354e
[fabric] Make RCTViewComponentView to be layer-backed by enabling wan…
shwanton Apr 27, 2024
a862170
[fabric] Clean up explicit namespace references in View component
Feb 22, 2024
8f90aa3
[fabric] Add support for setting a tool tip on View component
Feb 22, 2024
121165d
[fabric] Add cursor prop to View component
Feb 23, 2024
66dcfc7
[fabric] Add support for updating cursor to View component
Feb 23, 2024
5a8d176
[fabric] TextInput should get focus with `autoFocus` prop
shwanton Mar 13, 2024
1ee22c8
[fabric] Fix random text display for undefined text content
Mar 26, 2024
8918fda
[fabric] TextInput should handle pasted types prop
shwanton Apr 25, 2024
1483eae
[upstream][paper] Fix crash when statically enabling wantsUpdateLayer…
Feb 22, 2024
387db94
[fabric][touch-handler] Remove `cancelTouchWithEvent` till surface to…
shwanton May 1, 2024
6b80a5f
[fabric] Refactor MacOS view props & emitters
shwanton Apr 30, 2024
5375f8a
[fabric] Revert to Core Cursor implementation
shwanton May 1, 2024
855aed1
[fabric] Fix warning & formatting
shwanton May 1, 2024
2ee90c1
Merge branch 'shwanton/fabric-core-fixes' into fabric/more
Saadnajmi Aug 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#if TARGET_OS_OSX // [macOS

#import <React/RCTUIKit.h>

#import "RCTTextUIKit.h"

#import <React/RCTBackedTextInputDelegate.h>
#import <React/RCTBackedTextInputViewProtocol.h>

NS_ASSUME_NONNULL_BEGIN

@interface RCTWrappedTextView : RCTPlatformView <RCTBackedTextInputViewProtocol>

@property (nonatomic, weak) id<RCTBackedTextInputDelegate> textInputDelegate;
@property (assign) BOOL hideVerticalScrollIndicator;

@end

NS_ASSUME_NONNULL_END

#endif // macOS]
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#if TARGET_OS_OSX // [macOS

#import <React/RCTWrappedTextView.h>

#import <React/RCTUITextView.h>
#import <React/RCTTextAttributes.h>

@implementation RCTWrappedTextView {
RCTUITextView *_forwardingTextView;
RCTUIScrollView *_scrollView;
RCTClipView *_clipView;
}

- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

self.hideVerticalScrollIndicator = NO;

_scrollView = [[RCTUIScrollView alloc] initWithFrame:self.bounds];
_scrollView.backgroundColor = [RCTUIColor clearColor];
_scrollView.drawsBackground = NO;
_scrollView.borderType = NSNoBorder;
_scrollView.hasHorizontalRuler = NO;
_scrollView.hasVerticalRuler = NO;
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[_scrollView setHasVerticalScroller:YES];
[_scrollView setHasHorizontalScroller:NO];

_clipView = [[RCTClipView alloc] initWithFrame:_scrollView.bounds];
[_scrollView setContentView:_clipView];

_forwardingTextView = [[RCTUITextView alloc] initWithFrame:_scrollView.bounds];
_forwardingTextView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_forwardingTextView.delegate = self;

_forwardingTextView.verticallyResizable = YES;
_forwardingTextView.horizontallyResizable = YES;
_forwardingTextView.textContainer.containerSize = NSMakeSize(FLT_MAX, FLT_MAX);
_forwardingTextView.textContainer.widthTracksTextView = YES;
_forwardingTextView.textInputDelegate = self;

_scrollView.documentView = _forwardingTextView;
_scrollView.contentView.postsBoundsChangedNotifications = YES;

// Enable the focus ring by default
_scrollView.enableFocusRing = YES;
[self addSubview:_scrollView];

// a register for those notifications on the content view.
#if !TARGET_OS_OSX // [macOS]
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(boundsDidChange:)
name:NSViewBoundsDidChangeNotification
object:_scrollView.contentView];
#else // [macOS
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(scrollViewDidScroll:)
name:NSViewBoundsDidChangeNotification
object:_scrollView.contentView];
#endif // macOS]
}

return self;
}

- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (BOOL)isFlipped
{
return YES;
}

#pragma mark -
#pragma mark Method forwarding to text view

- (void)forwardInvocation:(NSInvocation *)invocation
{
[invocation invokeWithTarget:_forwardingTextView];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
if ([_forwardingTextView respondsToSelector:selector]) {
return [_forwardingTextView methodSignatureForSelector:selector];
}

return [super methodSignatureForSelector:selector];
}

- (void)boundsDidChange:(NSNotification *)notification
{
}

#pragma mark -
#pragma mark First Responder forwarding

- (NSResponder *)responder
{
return _forwardingTextView;
}

- (BOOL)acceptsFirstResponder
{
return _forwardingTextView.acceptsFirstResponder;
}

- (BOOL)becomeFirstResponder
{
return [_forwardingTextView becomeFirstResponder];
}

- (BOOL)resignFirstResponder
{
return [_forwardingTextView resignFirstResponder];
}

#pragma mark -
#pragma mark Text Input delegate forwarding

- (id<RCTBackedTextInputDelegate>)textInputDelegate
{
return _forwardingTextView.textInputDelegate;
}

- (void)setTextInputDelegate:(id<RCTBackedTextInputDelegate>)textInputDelegate
{
_forwardingTextView.textInputDelegate = textInputDelegate;
}

#pragma mark -
#pragma mark Scrolling control

#if TARGET_OS_OSX // [macOS
- (void)scrollViewDidScroll:(NSNotification *)notification
{
[self.textInputDelegate scrollViewDidScroll:_scrollView];
}
#endif // macOS]

- (BOOL)scrollEnabled
{
return _scrollView.isScrollEnabled;
}

- (void)setScrollEnabled:(BOOL)scrollEnabled
{
if (scrollEnabled) {
_scrollView.scrollEnabled = YES;
[_clipView setConstrainScrolling:NO];
} else {
_scrollView.scrollEnabled = NO;
[_clipView setConstrainScrolling:YES];
}
}

- (BOOL)shouldShowVerticalScrollbar
{
// Hide vertical scrollbar if explicity set to NO
if (self.hideVerticalScrollIndicator) {
return NO;
}

// Hide vertical scrollbar if attributed text overflows view
CGSize textViewSize = [_forwardingTextView intrinsicContentSize];
NSClipView *clipView = (NSClipView *)_scrollView.contentView;
if (textViewSize.height > clipView.bounds.size.height) {
return YES;
};

return NO;
}

- (void)textInputDidChange
{
[_scrollView setHasVerticalScroller:[self shouldShowVerticalScrollbar]];
}

- (void)setAttributedText:(NSAttributedString *)attributedText
{
[_forwardingTextView setAttributedText:attributedText];
[_scrollView setHasVerticalScroller:[self shouldShowVerticalScrollbar]];
}

#pragma mark -
#pragma mark Text Container Inset override for NSTextView

// This method is there to match the textContainerInset property on RCTUITextField
- (void)setTextContainerInset:(UIEdgeInsets)textContainerInsets
{
// RCTUITextView has logic in setTextContainerInset[s] to convert th UIEdgeInsets to a valid NSSize struct
_forwardingTextView.textContainerInsets = textContainerInsets;
}

#pragma mark -
#pragma mark Focus ring

- (BOOL)enableFocusRing
{
return _scrollView.enableFocusRing;
}

- (void)setEnableFocusRing:(BOOL)enableFocusRing
{
_scrollView.enableFocusRing = enableFocusRing;
}

@end

#endif // macOS]
Original file line number Diff line number Diff line change
Expand Up @@ -398,17 +398,17 @@ - (void)textViewDidChangeSelection:(__unused UITextView *)textView
[self textViewProbablyDidChangeSelection];
}

#endif // [macOS]

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
- (void)scrollViewDidScroll:(RCTUIScrollView *)scrollView // [macOS]
{
if ([_backedTextInputView.textInputDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) {
[_backedTextInputView.textInputDelegate scrollViewDidScroll:scrollView];
}
}

#endif // [macOS]

#if TARGET_OS_OSX // [macOS

#pragma mark - NSTextViewDelegate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign, readonly) BOOL textWasPasted;
#else // [macOS
@property (nonatomic, assign) BOOL textWasPasted;
@property (nonatomic, readonly) NSResponder *responder;
@property (nonatomic, assign) BOOL enableFocusRing;
#endif // macOS]
@property (nonatomic, assign, readonly) BOOL dictationRecognizing;
@property (nonatomic, assign) UIEdgeInsets textContainerInset;
Expand Down Expand Up @@ -88,6 +90,7 @@ NS_ASSUME_NONNULL_BEGIN
#if TARGET_OS_OSX // [macOS
// UITextInput method for OSX
- (CGSize)sizeThatFits:(CGSize)size;
- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes;
#endif // macOS]

// This protocol disallows direct access to `text` property because
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN
#if !TARGET_OS_OSX // [macOS]
@property (nonatomic, assign, getter=isEditable) BOOL editable;
#else // [macOS
@property (assign, getter=isEditable) BOOL editable;
@property (atomic, assign, getter=isEditable) BOOL editable;
#endif // macOS]
@property (nonatomic, getter=isScrollEnabled) BOOL scrollEnabled;
@property (nonatomic, strong, nullable) NSString *inputAccessoryViewID;
Expand All @@ -58,7 +58,7 @@ NS_ASSUME_NONNULL_BEGIN
#if TARGET_OS_OSX // [macOS
@property (nonatomic, copy, nullable) NSString *text;
@property (nonatomic, copy, nullable) NSAttributedString *attributedText;
@property (nonatomic, copy) NSDictionary<NSAttributedStringKey, id> *defaultTextAttributes;
@property (nonatomic, strong, nullable) NSDictionary<NSAttributedStringKey, id> *defaultTextAttributes;
@property (nullable, nonatomic, copy) NSDictionary<NSAttributedStringKey, id> *typingAttributes;
@property (nonatomic, assign) NSTextAlignment textAlignment;
@property (nonatomic, getter=isAutomaticTextReplacementEnabled) BOOL automaticTextReplacementEnabled;
Expand All @@ -69,6 +69,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong, nullable) RCTUIColor *selectionColor;
@property (weak, nullable) id<RCTUITextFieldDelegate> delegate;
@property (nonatomic, assign) CGFloat pointScaleFactor;

- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes;
#endif // macOS]

@property (nonatomic, getter=isGhostTextChanging) BOOL ghostTextChanging; // [macOS]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ @implementation RCTUITextField {
#endif // [macOS]
#if TARGET_OS_OSX // [macOS
BOOL _isUpdatingPlaceholderText;
NSArray<NSPasteboardType> *_readablePasteboardTypes;
#endif // macOS]
}

Expand Down Expand Up @@ -216,6 +217,11 @@ - (void)setTextContainerInset:(UIEdgeInsets)textContainerInset

#if TARGET_OS_OSX // [macOS

- (NSResponder *)responder
{
return self;
}

+ (Class)cellClass
{
return RCTUITextFieldCell.class;
Expand Down Expand Up @@ -705,5 +711,12 @@ - (void)keyUp:(NSEvent *)event {
}
}
#endif // macOS]

#if TARGET_OS_OSX // [macOS
- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes
{
_readablePasteboardTypes = readablePasteboardTypes;
}
#endif // macOS]

@end
9 changes: 8 additions & 1 deletion packages/react-native/React/Base/macOS/RCTUIKit.m
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ @implementation RCTUIView
BOOL _userInteractionEnabled;
NSTrackingArea *_trackingArea;
BOOL _mouseDownCanMoveWindow;
BOOL _respondsToDisplayLayer;
}

+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key
Expand Down Expand Up @@ -211,6 +212,7 @@ @implementation RCTUIView
self->_userInteractionEnabled = YES;
self->_enableFocusRing = YES;
self->_mouseDownCanMoveWindow = YES;
self->_respondsToDisplayLayer = [self respondsToSelector:@selector(displayLayer:)];
}
return self;
}
Expand Down Expand Up @@ -474,7 +476,12 @@ - (void)updateLayer
// so it has to be reset from the view's NSColor ivar.
[layer setBackgroundColor:[_backgroundColor CGColor]];
}
[(id<CALayerDelegate>)self displayLayer:layer];

// In Fabric, wantsUpdateLayer is always enabled and doesn't guarantee that
// the instance has a displayLayer method.
if (_respondsToDisplayLayer) {
[(id<CALayerDelegate>)self displayLayer:layer];
}
}

- (void)drawRect:(CGRect)rect
Expand Down
Loading
Loading