Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ NS_ASSUME_NONNULL_BEGIN
@interface RCTMultilineTextInputView : RCTBaseTextInputView

#if TARGET_OS_OSX // [TODO(macOS GH#774)

@property (nonatomic, assign) BOOL scrollEnabled;

- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes;
@property (nonatomic, assign) BOOL hideVerticalScrollIndicator;
#endif // ]TODO(macOS GH#774)

@end

NS_ASSUME_NONNULL_END
26 changes: 24 additions & 2 deletions Libraries/Text/TextInput/Multiline/RCTMultilineTextInputView.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ @implementation RCTMultilineTextInputView
{
#if TARGET_OS_OSX // [TODO(macOS GH#774)
RCTUIScrollView *_scrollView;
RCTClipView *_clipView;
#endif // ]TODO(macOS GH#774)
RCTUITextView *_backedTextInputView;
}
Expand All @@ -38,6 +39,9 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
_scrollView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[_scrollView setHasVerticalScroller:YES];

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

_backedTextInputView.verticallyResizable = YES;
_backedTextInputView.horizontallyResizable = YES;
_backedTextInputView.textContainer.containerSize = NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX);
Expand Down Expand Up @@ -94,17 +98,35 @@ - (void)setReactBorderInsets:(UIEdgeInsets)reactBorderInsets
[self setNeedsLayout];
}

- (void)setEnableFocusRing:(BOOL)enableFocusRing {
- (void)setEnableFocusRing:(BOOL)enableFocusRing
{
[super setEnableFocusRing:enableFocusRing];
if ([_scrollView respondsToSelector:@selector(setEnableFocusRing:)]) {
[_scrollView setEnableFocusRing:enableFocusRing];
}
}

- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes {
- (void)setReadablePasteBoardTypes:(NSArray<NSPasteboardType> *)readablePasteboardTypes
{
[_backedTextInputView setReadablePasteBoardTypes:readablePasteboardTypes];
}

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

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

- (BOOL)shouldShowVerticalScrollbar
{
// Hide vertical scrollbar if explicity set to NO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ - (RCTUIView *)view // TODO(macOS ISS#3536887)
RCT_REMAP_OSX_VIEW_PROPERTY(dataDetectorTypes, backedTextInputView.enabledTextCheckingTypes, NSTextCheckingTypes) // TODO(macOS GH#774)

#if TARGET_OS_OSX // [TODO(macOS GH#774)
RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(hideVerticalScrollIndicator, BOOL)
RCT_CUSTOM_VIEW_PROPERTY(pastedTypes, NSArray<NSPasteboardType>*, RCTUITextView)
{
Expand Down
2 changes: 1 addition & 1 deletion Libraries/Text/TextInput/Multiline/RCTUITextView.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong, nullable) NSString *inputAccessoryViewID;

#if TARGET_OS_OSX // [TODO(macOS GH#774)
@property (nonatomic, assign) BOOL scrollEnabled;
@property (nonatomic, getter=isScrollEnabled) BOOL scrollEnabled;
@property (nonatomic, strong, nullable) RCTUIColor *selectionColor; // TODO(OSS Candidate ISS#2710739)
@property (nonatomic, assign) UIEdgeInsets textContainerInsets;
@property (nonatomic, copy) NSString *text;
Expand Down
1 change: 0 additions & 1 deletion Libraries/Text/TextInput/RCTBaseTextInputViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ @implementation RCTBaseTextInputViewManager
RCT_REMAP_OSX_VIEW_PROPERTY(spellCheck, backedTextInputView.continuousSpellCheckingEnabled, BOOL) // TODO(macOS GH#774)
RCT_REMAP_NOT_OSX_VIEW_PROPERTY(caretHidden, backedTextInputView.caretHidden, BOOL) // TODO(macOS GH#774)
RCT_REMAP_NOT_OSX_VIEW_PROPERTY(clearButtonMode, backedTextInputView.clearButtonMode, UITextFieldViewMode) // TODO(macOS GH#774)
RCT_REMAP_VIEW_PROPERTY(scrollEnabled, backedTextInputView.scrollEnabled, BOOL)
RCT_REMAP_NOT_OSX_VIEW_PROPERTY(secureTextEntry, backedTextInputView.secureTextEntry, BOOL) // TODO(macOS GH#774)
RCT_EXPORT_VIEW_PROPERTY(autoFocus, BOOL)
RCT_EXPORT_VIEW_PROPERTY(blurOnSubmit, BOOL)
Expand Down
8 changes: 8 additions & 0 deletions React/Base/RCTUIKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,17 @@ CGPathRef UIBezierPathCreateCGPathRef(UIBezierPath *path);
@property (nonatomic, assign) BOOL alwaysBounceVertical;
// macOS specific properties
@property (nonatomic, assign) BOOL enableFocusRing;
@property (nonatomic, assign, getter=isScrollEnabled) BOOL scrollEnabled;

@end

@interface RCTClipView : NSClipView // [TODO(macOS GH#774)

@property (nonatomic, assign) BOOL constrainScrolling;

@end // ]TODO(macOS GH#774)


NS_INLINE RCTPlatformView *RCTUIViewHitTestWithEvent(RCTPlatformView *view, CGPoint point, __unused UIEvent *event)
{
return [view hitTest:point];
Expand Down
33 changes: 33 additions & 0 deletions React/Base/macOS/RCTUIKit.m
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,15 @@ - (void)setCursor:(NSInteger)cursor

@implementation RCTUIScrollView // TODO(macOS ISS#3536887)

- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self.scrollEnabled = YES;
}

return self;
}

- (void)setEnableFocusRing:(BOOL)enableFocusRing {
if (_enableFocusRing != enableFocusRing) {
_enableFocusRing = enableFocusRing;
Expand Down Expand Up @@ -542,6 +551,7 @@ - (void)setAlwaysBounceVertical:(BOOL)alwaysBounceVertical
self.verticalScrollElasticity = alwaysBounceVertical ? NSScrollElasticityAllowed : NSScrollElasticityNone;
}


@end

BOOL RCTUIViewSetClipsToBounds(RCTPlatformView *view)
Expand All @@ -557,3 +567,26 @@ BOOL RCTUIViewSetClipsToBounds(RCTPlatformView *view)

return clipsToBounds;
}

@implementation RCTClipView

- (instancetype)initWithFrame:(NSRect)frameRect
{
if (self = [super initWithFrame:frameRect]) {
self.constrainScrolling = NO;
self.drawsBackground = NO;
}

return self;
}

- (NSRect)constrainBoundsRect:(NSRect)proposedBounds
{
if (self.constrainScrolling) {
return NSMakeRect(0, 0, 0, 0);
}

return [super constrainBoundsRect:proposedBounds];
}

@end
2 changes: 1 addition & 1 deletion React/Views/ScrollView/RCTScrollView.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ - (BOOL)isFlipped

- (void)scrollWheel:(NSEvent *)theEvent
{
if (!self.scrollEnabled) {
if (!self.isScrollEnabled) {
[[self nextResponder] scrollWheel:theEvent];
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,14 @@ exports.examples = ([
multiline={true}
style={styles.multiline}
/>
{/* [TODO(macOS GH#774) */}
<TextInput
placeholder="multiline text input with scroll disabled"
multiline={true}
scrollEnabled={false}
style={styles.multiline}
/>
{/* [TODO(macOS GH#774) */}
<TextInput
placeholder="multiline text input with vertical scrollbar hidden"
multiline={true}
Expand Down