not-react-native-macos 0.87.1-rc.6 → 0.87.1-rc.7

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.
@@ -88,7 +88,11 @@ class AppStateImpl {
88
88
  new NativeEventEmitter(
89
89
  // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior
90
90
  // If you want to use the native module on other platforms, please remove this condition and test its behavior
91
- Platform.OS !== 'ios' ? null : NativeAppState,
91
+ // [macOS] macOS uses this parameter too: the module is an
92
+ // RCTEventEmitter subclass here, exactly as it is on iOS.
93
+ Platform.OS !== 'ios' && Platform.OS !== 'macos'
94
+ ? null
95
+ : NativeAppState,
92
96
  );
93
97
  this._emitter = emitter;
94
98
 
@@ -234,7 +234,8 @@ const Button: component(
234
234
  const buttonStyles: Array<ViewStyleProp> = [styles.button];
235
235
  const textStyles: Array<TextStyleProp> = [styles.text];
236
236
  if (color) {
237
- if (Platform.OS === 'ios') {
237
+ // [macOS] Apple platforms tint the label; Android tints the background.
238
+ if (Platform.OS === 'ios' || Platform.OS === 'macos') {
238
239
  textStyles.push({color: color});
239
240
  } else {
240
241
  buttonStyles.push({backgroundColor: color});
@@ -77,7 +77,11 @@ class KeyboardImpl {
77
77
  new NativeEventEmitter(
78
78
  // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior
79
79
  // If you want to use the native module on other platforms, please remove this condition and test its behavior
80
- Platform.OS !== 'ios' ? null : NativeKeyboardObserver,
80
+ // [macOS] macOS uses this parameter too: the module is an
81
+ // RCTEventEmitter subclass here, exactly as it is on iOS.
82
+ Platform.OS !== 'ios' && Platform.OS !== 'macos'
83
+ ? null
84
+ : NativeKeyboardObserver,
81
85
  );
82
86
 
83
87
  constructor() {
@@ -1101,7 +1101,11 @@ class ScrollView extends React.Component<ScrollViewProps, ScrollViewState> {
1101
1101
  },
1102
1102
  animated?: boolean, // deprecated, put this inside the rect argument instead
1103
1103
  ) => {
1104
- invariant(Platform.OS === 'ios', 'zoomToRect is not implemented');
1104
+ // [macOS] The AppKit scroll view zooms as well.
1105
+ invariant(
1106
+ Platform.OS === 'ios' || Platform.OS === 'macos',
1107
+ 'zoomToRect is not implemented',
1108
+ );
1105
1109
  if ('animated' in rect) {
1106
1110
  this._animated = rect.animated;
1107
1111
  delete rect.animated;
@@ -75,7 +75,11 @@ if (Platform.OS === 'android') {
75
75
  AndroidTextInput = require('./AndroidTextInputNativeComponent').default;
76
76
  AndroidTextInputCommands =
77
77
  require('./AndroidTextInputNativeComponent').Commands;
78
- } else if (Platform.OS === 'ios') {
78
+ // [macOS] macOS uses the same two Apple-platform components. Without this
79
+ // branch neither module is ever required, both locals stay undefined, and
80
+ // the render below -- also gated on `ios` -- returns nothing at all: a
81
+ // TextInput silently renders as empty space, with no error anywhere.
82
+ } else if (Platform.OS === 'ios' || Platform.OS === 'macos') {
79
83
  RCTSinglelineTextInputView =
80
84
  require('./RCTSingelineTextInputNativeComponent').default;
81
85
  RCTSinglelineTextInputNativeCommands =
@@ -564,7 +568,8 @@ function InternalTextInput(props: TextInputProps): React.Node {
564
568
  }
565
569
  }
566
570
 
567
- if (Platform.OS === 'ios') {
571
+ // [macOS] The Apple-platform render path; see the require above.
572
+ if (Platform.OS === 'ios' || Platform.OS === 'macos') {
568
573
  const RCTTextInputView =
569
574
  props.multiline === true
570
575
  ? RCTMultilineTextInputView
@@ -87,7 +87,9 @@ function focusTextInput(textField: ?HostInstance) {
87
87
 
88
88
  if (textField != null) {
89
89
  const fieldCanBeFocused =
90
- currentlyFocusedInputRef !== textField &&
90
+ // [macOS] On a desktop any view can hold focus, so the currently focused
91
+ // *input* is not a reliable answer to whether this field already has it.
92
+ (Platform.OS === 'macos' || currentlyFocusedInputRef !== textField) &&
91
93
  // $FlowFixMe[prop-missing] - `currentProps` is missing in `NativeMethods`
92
94
  textField.currentProps?.editable !== false;
93
95
 
@@ -95,7 +97,9 @@ function focusTextInput(textField: ?HostInstance) {
95
97
  return;
96
98
  }
97
99
  focusInput(textField);
98
- if (Platform.OS === 'ios') {
100
+ // [macOS] The commands are declared by the Apple-platform native
101
+ // components, which macOS shares.
102
+ if (Platform.OS === 'ios' || Platform.OS === 'macos') {
99
103
  // This isn't necessarily a single line text input
100
104
  // But commands don't actually care as long as the thing being passed in
101
105
  // actually has a command with that name. So this should work with single
@@ -126,7 +130,9 @@ function blurTextInput(textField: ?HostInstance) {
126
130
 
127
131
  if (currentlyFocusedInputRef === textField && textField != null) {
128
132
  blurInput(textField);
129
- if (Platform.OS === 'ios') {
133
+ // [macOS] The commands are declared by the Apple-platform native
134
+ // components, which macOS shares.
135
+ if (Platform.OS === 'ios' || Platform.OS === 'macos') {
130
136
  // This isn't necessarily a single line text input
131
137
  // But commands don't actually care as long as the thing being passed in
132
138
  // actually has a command with that name. So this should work with single
@@ -71,7 +71,12 @@ export default class NativeEventEmitter<
71
71
  * an invariant error if undefined.
72
72
  */
73
73
  constructor(nativeModule?: ?NativeModule) {
74
- if (Platform.OS === 'ios') {
74
+ // [macOS] Same requirement on macOS: the module backing the emitter is an
75
+ // RCTEventEmitter subclass here too, so a null one is a bug rather than a
76
+ // platform difference. This only holds because the callers that used to
77
+ // pass `Platform.OS !== 'ios' ? null : NativeX` now pass the module on
78
+ // macOS as well -- widening this without those is an import-time crash.
79
+ if (Platform.OS === 'ios' || Platform.OS === 'macos') {
75
80
  invariant(
76
81
  nativeModule != null,
77
82
  '`new NativeEventEmitter()` requires a non-null argument.',
@@ -23,7 +23,12 @@ type LinkingEventDefinitions = {
23
23
 
24
24
  class LinkingImpl extends NativeEventEmitter<LinkingEventDefinitions> {
25
25
  constructor() {
26
- super(Platform.OS === 'ios' ? nullthrows(NativeLinkingManager) : undefined);
26
+ // [macOS] RCTLinkingManager is built for macOS too.
27
+ super(
28
+ Platform.OS === 'ios' || Platform.OS === 'macos'
29
+ ? nullthrows(NativeLinkingManager)
30
+ : undefined,
31
+ );
27
32
  }
28
33
 
29
34
  /**
@@ -43,7 +43,11 @@ const ModalEventEmitter =
43
43
  ? new NativeEventEmitter<ModalEventDefinitions>(
44
44
  // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior
45
45
  // If you want to use the native module on other platforms, please remove this condition and test its behavior
46
- Platform.OS !== 'ios' ? null : NativeModalManager,
46
+ // [macOS] macOS uses this parameter too: the module is an
47
+ // RCTEventEmitter subclass here, exactly as it is on iOS.
48
+ Platform.OS !== 'ios' && Platform.OS !== 'macos'
49
+ ? null
50
+ : NativeModalManager,
47
51
  )
48
52
  : null;
49
53
 
@@ -53,6 +53,11 @@ if (Platform.OS === 'web') {
53
53
  document.addEventListener('touchstart', disableHover, true);
54
54
  document.addEventListener('touchmove', disableHover, true);
55
55
  document.addEventListener('mousemove', enableHover, true);
56
+ // [macOS] A Mac always has a pointer, and unlike the web there is no touch
57
+ // input to disable hover for. Without this `onHoverIn` / `onHoverOut` never
58
+ // fire on Pressable, because Pressability checks this flag first.
59
+ } else if (Platform.OS === 'macos') {
60
+ isEnabled = true;
56
61
  }
57
62
  }
58
63
 
@@ -67,7 +67,11 @@ const PushNotificationEmitter =
67
67
  new NativeEventEmitter<NativePushNotificationIOSEventDefinitions>(
68
68
  // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior
69
69
  // If you want to use the native module on other platforms, please remove this condition and test its behavior
70
- Platform.OS !== 'ios' ? null : NativePushNotificationManagerIOS,
70
+ // [macOS] macOS uses this parameter too: the module is an
71
+ // RCTEventEmitter subclass here, exactly as it is on iOS.
72
+ Platform.OS !== 'ios' && Platform.OS !== 'macos'
73
+ ? null
74
+ : NativePushNotificationManagerIOS,
71
75
  );
72
76
 
73
77
  const _notifHandlers = new Map<string, void | EventSubscription>();
@@ -155,7 +155,8 @@ function lazifyViewManagerConfig(viewName: string) {
155
155
  * only needed for iOS, which puts the constants in the ViewManager
156
156
  * namespace instead of UIManager, unlike Android.
157
157
  */
158
- if (Platform.OS === 'ios') {
158
+ // [macOS] Apple platforms namespace view-manager constants the same way.
159
+ if (Platform.OS === 'ios' || Platform.OS === 'macos') {
159
160
  Object.keys(getConstants()).forEach(viewName => {
160
161
  lazifyViewManagerConfig(viewName);
161
162
  });
@@ -53,7 +53,11 @@ if (__DEV__) {
53
53
  const emitter = new NativeEventEmitter<DevSettingsEventDefinitions>(
54
54
  // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior
55
55
  // If you want to use the native module on other platforms, please remove this condition and test its behavior
56
- Platform.OS !== 'ios' ? null : NativeDevSettings,
56
+ // [macOS] macOS uses this parameter too: the module is an
57
+ // RCTEventEmitter subclass here, exactly as it is on iOS.
58
+ Platform.OS !== 'ios' && Platform.OS !== 'macos'
59
+ ? null
60
+ : NativeDevSettings,
57
61
  );
58
62
  const subscriptions = new Map<string, EventSubscription>();
59
63
 
@@ -192,7 +192,8 @@ const HMRClient: HMRClientNativeInterface = {
192
192
  Try the following to fix the issue:
193
193
  - Ensure that Metro is running and available on the same network`;
194
194
 
195
- if (Platform.OS === 'ios') {
195
+ // [macOS] The AppDelegate advice is just as true here.
196
+ if (Platform.OS === 'ios' || Platform.OS === 'macos') {
196
197
  error += `
197
198
  - Ensure that the Metro URL is correctly set in AppDelegate`;
198
199
  } else {
@@ -349,7 +350,8 @@ function flushEarlyLogs(client: MetroHMRClient) {
349
350
 
350
351
  function dismissRedbox() {
351
352
  if (
352
- Platform.OS === 'ios' &&
353
+ // [macOS] RedBox is an Apple-platform module; macOS has it too.
354
+ (Platform.OS === 'ios' || Platform.OS === 'macos') &&
353
355
  NativeRedBox != null &&
354
356
  NativeRedBox.dismiss != null
355
357
  ) {
@@ -141,7 +141,11 @@ class WebSocket extends EventTarget {
141
141
  this._eventEmitter = new NativeEventEmitter(
142
142
  // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior
143
143
  // If you want to use the native module on other platforms, please remove this condition and test its behavior
144
- Platform.OS !== 'ios' ? null : NativeWebSocketModule,
144
+ // [macOS] macOS uses this parameter too: the module is an
145
+ // RCTEventEmitter subclass here, exactly as it is on iOS.
146
+ Platform.OS !== 'ios' && Platform.OS !== 'macos'
147
+ ? null
148
+ : NativeWebSocketModule,
145
149
  );
146
150
  this._socketId = nextWebSocketId++;
147
151
  this._registerEvents();
@@ -169,7 +169,11 @@ const WebSocketInterceptor = {
169
169
  eventEmitter = new NativeEventEmitter(
170
170
  // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior
171
171
  // If you want to use the native module on other platforms, please remove this condition and test its behavior
172
- Platform.OS !== 'ios' ? null : NativeWebSocketModule,
172
+ // [macOS] macOS uses this parameter too: the module is an
173
+ // RCTEventEmitter subclass here, exactly as it is on iOS.
174
+ Platform.OS !== 'ios' && Platform.OS !== 'macos'
175
+ ? null
176
+ : NativeWebSocketModule,
173
177
  );
174
178
  WebSocketInterceptor._registerEvents();
175
179
 
@@ -158,6 +158,35 @@ typedef NS_ENUM(NSInteger, UIKeyboardAppearance) {
158
158
  // UIKit's per-field default attributes. NSTextField applies typing attributes
159
159
  // through its field editor instead, so these are stored and applied on edit.
160
160
  @property (nonatomic, copy, nullable) NSDictionary<NSAttributedStringKey, id> *defaultTextAttributes;
161
+ // The attributes newly typed text takes on. NSTextField has no such property:
162
+ // editing happens in the window's shared field editor, which is an NSTextView
163
+ // and does. Reads and writes are forwarded there while editing, and held here
164
+ // otherwise so the value survives between edits.
165
+ @property (nonatomic, copy, null_resettable) NSDictionary<NSAttributedStringKey, id> *typingAttributes;
166
+ // NSTextField spells the styled value attributedStringValue.
167
+ @property (nonatomic, copy, nullable) NSAttributedString *attributedText;
168
+ // NSControl spells it alignment.
169
+ @property (nonatomic, assign) NSTextAlignment textAlignment;
170
+ // UIKit's clear button. NSTextField has no equivalent, so this is stored and
171
+ // otherwise unused -- a Mac text field does not show one.
172
+ @property (nonatomic, assign) UITextFieldViewMode clearButtonMode;
173
+ // UIKit hangs custom keyboards and toolbars off the responder. AppKit has no
174
+ // software keyboard, so these are stored and never presented.
175
+ @property (nonatomic, strong, nullable) UIView *inputView;
176
+ @property (nonatomic, strong, nullable) UIView *inputAccessoryView;
177
+ // Traits UITextInputTraits declares as @optional. A protocol property creates
178
+ // no storage, so each one an ObjC class is expected to answer has to be
179
+ // synthesized by that class -- omitting them is an unrecognized selector at
180
+ // the first access, not a compile error.
181
+ @property (nonatomic, assign) UITextSmartInsertDeleteType smartInsertDeleteType;
182
+ @property (nonatomic, assign) UITextSmartQuotesType smartQuotesType;
183
+ @property (nonatomic, assign) UITextSmartDashesType smartDashesType;
184
+ @property (nonatomic, copy, nullable) NSString *textContentType;
185
+ @property (nonatomic, strong, nullable) id passwordRules;
186
+ @property (nonatomic, assign) BOOL enablesReturnKeyAutomatically;
187
+ // UIKit tints the caret and selection through the view; AppKit takes it from
188
+ // the field editor's insertion-point colour.
189
+ @property (nonatomic, strong, nullable) UIColor *tintColor;
161
190
  // NSTextField spells it placeholderAttributedString.
162
191
  @property (nonatomic, copy, nullable) NSAttributedString *attributedPlaceholder;
163
192
  // UIResponder's editing-menu hook; NSResponder has -validateUserInterfaceItem:.
@@ -219,6 +248,27 @@ typedef NS_ENUM(NSInteger, UIKeyboardAppearance) {
219
248
  @property (nonatomic, assign) UIReturnKeyType returnKeyType;
220
249
  @property (nonatomic, copy, nullable) NSString *text;
221
250
  @property (nonatomic, weak, nullable) id<UITextDropDelegate> textDropDelegate;
251
+ // As on UITextField: UITextInputTraits declares these @optional, so a class
252
+ // expected to answer them has to synthesize its own storage.
253
+ @property (nonatomic, assign) UITextAutocapitalizationType autocapitalizationType;
254
+ @property (nonatomic, assign) UITextAutocorrectionType autocorrectionType;
255
+ @property (nonatomic, assign) UITextSpellCheckingType spellCheckingType;
256
+ @property (nonatomic, assign) UIKeyboardAppearance keyboardAppearance;
257
+ @property (nonatomic, assign) UITextSmartInsertDeleteType smartInsertDeleteType;
258
+ @property (nonatomic, assign) UITextSmartQuotesType smartQuotesType;
259
+ @property (nonatomic, assign) UITextSmartDashesType smartDashesType;
260
+ @property (nonatomic, assign, getter=isSecureTextEntry) BOOL secureTextEntry;
261
+ @property (nonatomic, assign) BOOL enablesReturnKeyAutomatically;
262
+ @property (nonatomic, copy, nullable) NSString *textContentType;
263
+ @property (nonatomic, strong, nullable) id passwordRules;
264
+ // UIKit's text view scrolls itself. NSTextView is the document view of an
265
+ // enclosing NSScrollView, so this forwards to that.
266
+ @property (nonatomic, assign, getter=isScrollEnabled) BOOL scrollEnabled;
267
+ @property (nonatomic, assign) CGPoint contentOffset;
268
+ @property (nonatomic, assign) CGFloat zoomScale;
269
+ @property (nonatomic, strong, nullable) UIView *inputView;
270
+ @property (nonatomic, strong, nullable) UIView *inputAccessoryView;
271
+ @property (nonatomic, assign) UIDataDetectorTypes dataDetectorTypes;
222
272
  @end
223
273
 
224
274
  // UIKit's editing notifications. AppKit posts NSControlTextDidChange and
@@ -78,10 +78,141 @@
78
78
 
79
79
  @end
80
80
 
81
- @implementation UITextField
81
+ @implementation UITextField {
82
+ NSDictionary<NSAttributedStringKey, id> *_typingAttributes;
83
+ }
82
84
 
83
85
  UIKIT_COMPAT_TEXT_INPUT_GEOMETRY
84
86
 
87
+ /**
88
+ * The live field editor, when this field is the one being edited.
89
+ *
90
+ * `-fieldEditor:forObject:` with NO does not create one, so this is nil unless
91
+ * editing is actually under way -- which is what makes it safe to ask for on
92
+ * every access.
93
+ */
94
+ - (NSTextView *)uikitCompat_activeFieldEditor
95
+ {
96
+ NSText *editor = [self.window fieldEditor:NO forObject:self];
97
+ if ([editor isKindOfClass:[NSTextView class]] && self.currentEditor == editor) {
98
+ return (NSTextView *)editor;
99
+ }
100
+ return nil;
101
+ }
102
+
103
+ @synthesize smartInsertDeleteType = _smartInsertDeleteType;
104
+ @synthesize smartQuotesType = _smartQuotesType;
105
+ @synthesize smartDashesType = _smartDashesType;
106
+ @synthesize textContentType = _textContentType;
107
+ @synthesize passwordRules = _passwordRules;
108
+ @synthesize enablesReturnKeyAutomatically = _enablesReturnKeyAutomatically;
109
+
110
+ /**
111
+ * Marked text is an in-progress IME composition. AppKit tracks it on the field
112
+ * editor, so there is nothing marked when the field is not being edited.
113
+ */
114
+ - (UITextRange *)markedTextRange
115
+ {
116
+ NSTextView *editor = [self uikitCompat_activeFieldEditor];
117
+ if (editor == nil || !editor.hasMarkedText) {
118
+ return nil;
119
+ }
120
+ NSRange range = editor.markedRange;
121
+ return [UITextRange rangeWithStart:[UITextPosition positionWithOffset:(NSInteger)range.location]
122
+ end:[UITextPosition positionWithOffset:(NSInteger)(range.location + range.length)]];
123
+ }
124
+
125
+ - (UITextInputMode *)textInputMode
126
+ {
127
+ // UIKit reports the software keyboard's language. AppKit has no software
128
+ // keyboard, and no caller here does more than null-check the result.
129
+ return nil;
130
+ }
131
+
132
+ - (UIColor *)tintColor
133
+ {
134
+ NSTextView *editor = [self uikitCompat_activeFieldEditor];
135
+ return editor != nil ? editor.insertionPointColor : nil;
136
+ }
137
+
138
+ - (void)setTintColor:(UIColor *)tintColor
139
+ {
140
+ NSTextView *editor = [self uikitCompat_activeFieldEditor];
141
+ if (editor != nil && tintColor != nil) {
142
+ editor.insertionPointColor = tintColor;
143
+ }
144
+ }
145
+
146
+ - (NSAttributedString *)attributedText
147
+ {
148
+ return self.attributedStringValue;
149
+ }
150
+
151
+ - (void)setAttributedText:(NSAttributedString *)attributedText
152
+ {
153
+ self.attributedStringValue = attributedText ?: [[NSAttributedString alloc] initWithString:@""];
154
+ }
155
+
156
+ - (NSTextAlignment)textAlignment
157
+ {
158
+ return self.alignment;
159
+ }
160
+
161
+ - (void)setTextAlignment:(NSTextAlignment)textAlignment
162
+ {
163
+ self.alignment = textAlignment;
164
+ }
165
+
166
+ /**
167
+ * The selection, which on AppKit lives in the field editor rather than the
168
+ * field. With no editor there is nothing selected, and UIKit reports nil for
169
+ * a field that is not being edited too.
170
+ */
171
+ - (UITextRange *)selectedTextRange
172
+ {
173
+ NSTextView *editor = [self uikitCompat_activeFieldEditor];
174
+ if (editor == nil) {
175
+ return nil;
176
+ }
177
+ NSRange range = editor.selectedRange;
178
+ return [UITextRange rangeWithStart:[UITextPosition positionWithOffset:(NSInteger)range.location]
179
+ end:[UITextPosition positionWithOffset:(NSInteger)(range.location + range.length)]];
180
+ }
181
+
182
+ - (void)setSelectedTextRange:(UITextRange *)selectedTextRange
183
+ {
184
+ NSTextView *editor = [self uikitCompat_activeFieldEditor];
185
+ if (editor == nil || selectedTextRange == nil) {
186
+ return;
187
+ }
188
+ NSInteger start = MAX((NSInteger)0, selectedTextRange.start.offset);
189
+ NSInteger end = MAX(start, selectedTextRange.end.offset);
190
+ NSInteger length = (NSInteger)self.stringValue.length;
191
+ start = MIN(start, length);
192
+ end = MIN(end, length);
193
+ editor.selectedRange = NSMakeRange((NSUInteger)start, (NSUInteger)(end - start));
194
+ }
195
+
196
+ - (NSDictionary<NSAttributedStringKey, id> *)typingAttributes
197
+ {
198
+ NSTextView *editor = [self uikitCompat_activeFieldEditor];
199
+ if (editor != nil) {
200
+ return editor.typingAttributes;
201
+ }
202
+ // Between edits there is no field editor to ask. UIKit's own default for a
203
+ // field that was never typed into is its default text attributes.
204
+ return _typingAttributes ?: self.defaultTextAttributes ?: @{};
205
+ }
206
+
207
+ - (void)setTypingAttributes:(NSDictionary<NSAttributedStringKey, id> *)typingAttributes
208
+ {
209
+ _typingAttributes = [typingAttributes copy];
210
+ NSTextView *editor = [self uikitCompat_activeFieldEditor];
211
+ if (editor != nil) {
212
+ editor.typingAttributes = _typingAttributes ?: @{};
213
+ }
214
+ }
215
+
85
216
  - (UITextPosition *)endOfDocument
86
217
  {
87
218
  return [UITextPosition positionWithOffset:(NSInteger)self.stringValue.length];
@@ -223,6 +354,85 @@ UIKIT_COMPAT_TEXT_INPUT_GEOMETRY
223
354
 
224
355
  @implementation UITextView
225
356
 
357
+ @synthesize autocapitalizationType = _autocapitalizationType;
358
+ @synthesize autocorrectionType = _autocorrectionType;
359
+ @synthesize spellCheckingType = _spellCheckingType;
360
+ @synthesize keyboardAppearance = _keyboardAppearance;
361
+ @synthesize smartInsertDeleteType = _smartInsertDeleteType;
362
+ @synthesize smartQuotesType = _smartQuotesType;
363
+ @synthesize smartDashesType = _smartDashesType;
364
+ @synthesize secureTextEntry = _secureTextEntry;
365
+ @synthesize enablesReturnKeyAutomatically = _enablesReturnKeyAutomatically;
366
+ @synthesize textContentType = _textContentType;
367
+ @synthesize passwordRules = _passwordRules;
368
+ @synthesize inputView = _inputView;
369
+ @synthesize inputAccessoryView = _inputAccessoryView;
370
+ @synthesize dataDetectorTypes = _dataDetectorTypes;
371
+ @synthesize zoomScale = _zoomScale;
372
+
373
+ /**
374
+ * UIKit's text view scrolls on its own. NSTextView is the document view inside
375
+ * an NSScrollView, so scrolling is a property of the enclosing view -- and
376
+ * there may not be one, when the text view is used unwrapped.
377
+ */
378
+ - (BOOL)isScrollEnabled
379
+ {
380
+ NSScrollView *scrollView = self.enclosingScrollView;
381
+ return scrollView != nil ? (scrollView.hasVerticalScroller || scrollView.hasHorizontalScroller) : NO;
382
+ }
383
+
384
+ - (void)setScrollEnabled:(BOOL)scrollEnabled
385
+ {
386
+ NSScrollView *scrollView = self.enclosingScrollView;
387
+ scrollView.hasVerticalScroller = scrollEnabled;
388
+ scrollView.hasHorizontalScroller = NO;
389
+ }
390
+
391
+ - (CGPoint)contentOffset
392
+ {
393
+ NSScrollView *scrollView = self.enclosingScrollView;
394
+ return scrollView != nil ? scrollView.contentView.bounds.origin : CGPointZero;
395
+ }
396
+
397
+ - (void)setContentOffset:(CGPoint)contentOffset
398
+ {
399
+ [self.enclosingScrollView.contentView scrollToPoint:contentOffset];
400
+ }
401
+
402
+ - (UITextInputMode *)textInputMode
403
+ {
404
+ // No software keyboard on macOS; callers only null-check this.
405
+ return nil;
406
+ }
407
+
408
+ - (UITextRange *)markedTextRange
409
+ {
410
+ if (!self.hasMarkedText) {
411
+ return nil;
412
+ }
413
+ NSRange range = self.markedRange;
414
+ return [UITextRange rangeWithStart:[UITextPosition positionWithOffset:(NSInteger)range.location]
415
+ end:[UITextPosition positionWithOffset:(NSInteger)(range.location + range.length)]];
416
+ }
417
+
418
+ - (UITextRange *)selectedTextRange
419
+ {
420
+ NSRange range = self.selectedRange;
421
+ return [UITextRange rangeWithStart:[UITextPosition positionWithOffset:(NSInteger)range.location]
422
+ end:[UITextPosition positionWithOffset:(NSInteger)(range.location + range.length)]];
423
+ }
424
+
425
+ - (void)setSelectedTextRange:(UITextRange *)selectedTextRange
426
+ {
427
+ if (selectedTextRange == nil) {
428
+ return;
429
+ }
430
+ NSInteger length = (NSInteger)self.string.length;
431
+ NSInteger start = MIN(MAX((NSInteger)0, selectedTextRange.start.offset), length);
432
+ NSInteger end = MIN(MAX(start, selectedTextRange.end.offset), length);
433
+ self.selectedRange = NSMakeRange((NSUInteger)start, (NSUInteger)(end - start));
434
+ }
435
+
226
436
  UIKIT_COMPAT_TEXT_INPUT_GEOMETRY
227
437
 
228
438
  - (UITextPosition *)endOfDocument
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "not-react-native-macos",
3
- "version": "0.87.1-rc.6",
3
+ "version": "0.87.1-rc.7",
4
4
  "description": "A framework for building native apps using React",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -489,7 +489,11 @@ export default {
489
489
  nativeEventEmitter = new NativeEventEmitter(
490
490
  // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior
491
491
  // If you want to use the native module on other platforms, please remove this condition and test its behavior
492
- Platform.OS !== 'ios' ? null : NativeAnimatedModule,
492
+ // [macOS] macOS uses this parameter too: the module is an
493
+ // RCTEventEmitter subclass here, exactly as it is on iOS.
494
+ Platform.OS !== 'ios' && Platform.OS !== 'macos'
495
+ ? null
496
+ : NativeAnimatedModule,
493
497
  );
494
498
  }
495
499
  return nativeEventEmitter;
@@ -70,7 +70,12 @@ const ExceptionsManager = {
70
70
  NativeModule.reportSoftException(message, stack, exceptionId);
71
71
  },
72
72
  dismissRedbox(): void {
73
- if (Platform.OS !== 'ios' && NativeModule.dismissRedbox) {
73
+ // [macOS] RedBox is dismissed natively on Apple platforms.
74
+ if (
75
+ Platform.OS !== 'ios' &&
76
+ Platform.OS !== 'macos' &&
77
+ NativeModule.dismissRedbox
78
+ ) {
74
79
  // TODO(T53311281): This is a noop on iOS now. Implement it.
75
80
  NativeModule.dismissRedbox();
76
81
  }