not-react-native-macos 0.87.1-rc.8 → 0.87.1-rc.9
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.
|
@@ -48,6 +48,13 @@ const textViewConfig = {
|
|
|
48
48
|
dataDetectorType: true,
|
|
49
49
|
android_hyphenationFrequency: true,
|
|
50
50
|
lineBreakStrategyIOS: true,
|
|
51
|
+
// [macOS] Text is a view too: ParagraphProps derives from ViewProps, which
|
|
52
|
+
// on macOS already carries these. Only the view config stood in the way --
|
|
53
|
+
// a prop missing from validAttributes never reaches C++ at all.
|
|
54
|
+
tooltip: true,
|
|
55
|
+
focusable: true,
|
|
56
|
+
enableFocusRing: true,
|
|
57
|
+
// macOS]
|
|
51
58
|
},
|
|
52
59
|
directEventTypes: {
|
|
53
60
|
topTextLayout: {
|
|
@@ -234,9 +234,22 @@ type TextBaseProps = Readonly<{
|
|
|
234
234
|
*
|
|
235
235
|
* @build-types emit-as-interface Uniwind compatibility
|
|
236
236
|
*/
|
|
237
|
+
// [macOS] Text carries the same three view props react-native-macos gives it.
|
|
238
|
+
// They work because ParagraphProps derives from ViewProps, which on macOS is
|
|
239
|
+
// HostPlatformViewProps.
|
|
240
|
+
export type TextPropsMacOS = Readonly<{
|
|
241
|
+
/** @platform macos */
|
|
242
|
+
tooltip?: ?string,
|
|
243
|
+
/** @platform macos */
|
|
244
|
+
focusable?: ?boolean,
|
|
245
|
+
/** @platform macos */
|
|
246
|
+
enableFocusRing?: ?boolean,
|
|
247
|
+
}>;
|
|
248
|
+
|
|
237
249
|
export type TextProps = Readonly<{
|
|
238
250
|
...TextPointerEventProps,
|
|
239
251
|
...TextPropsIOS,
|
|
252
|
+
...TextPropsMacOS, // [macOS]
|
|
240
253
|
...TextPropsAndroid,
|
|
241
254
|
...TextBaseProps,
|
|
242
255
|
...AccessibilityProps,
|
|
@@ -81,6 +81,8 @@
|
|
|
81
81
|
@implementation RCTUIKitCompatTextField {
|
|
82
82
|
NSDictionary<NSAttributedStringKey, id> *_typingAttributes;
|
|
83
83
|
NSMutableArray<NSArray *> *_controlEventTargets;
|
|
84
|
+
NSString *_placeholder;
|
|
85
|
+
BOOL _reportedEndEditing;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
UIKIT_COMPAT_TEXT_INPUT_GEOMETRY
|
|
@@ -333,13 +335,23 @@ UIKIT_COMPAT_TEXT_INPUT_GEOMETRY
|
|
|
333
335
|
return nil;
|
|
334
336
|
}
|
|
335
337
|
|
|
338
|
+
/**
|
|
339
|
+
* The plain and attributed placeholders are one value on NSTextField: setting
|
|
340
|
+
* `placeholderAttributedString` clears `placeholderString`, and the reverse.
|
|
341
|
+
* UIKit keeps both, and React Native relies on that -- it sets `placeholder`,
|
|
342
|
+
* builds `attributedPlaceholder` from it, and rebuilds that again whenever the
|
|
343
|
+
* text attributes change. Reading the plain one back through AppKit returns nil
|
|
344
|
+
* the second time round, so the placeholder is rebuilt as empty and silently
|
|
345
|
+
* disappears. Hold the string here instead.
|
|
346
|
+
*/
|
|
336
347
|
- (NSString *)placeholder
|
|
337
348
|
{
|
|
338
|
-
return self.placeholderString;
|
|
349
|
+
return _placeholder ?: self.placeholderString;
|
|
339
350
|
}
|
|
340
351
|
|
|
341
352
|
- (void)setPlaceholder:(NSString *)placeholder
|
|
342
353
|
{
|
|
354
|
+
_placeholder = [placeholder copy];
|
|
343
355
|
self.placeholderString = placeholder;
|
|
344
356
|
}
|
|
345
357
|
|
|
@@ -431,6 +443,7 @@ UIKIT_COMPAT_TEXT_INPUT_GEOMETRY
|
|
|
431
443
|
- (void)textDidBeginEditing:(NSNotification *)notification
|
|
432
444
|
{
|
|
433
445
|
[super textDidBeginEditing:notification];
|
|
446
|
+
_reportedEndEditing = NO;
|
|
434
447
|
[self uikitCompat_sendActionsForControlEvents:UIControlEventEditingDidBegin];
|
|
435
448
|
|
|
436
449
|
id<UITextFieldDelegate> delegate = [self uikitCompat_uiDelegate];
|
|
@@ -458,10 +471,21 @@ UIKIT_COMPAT_TEXT_INPUT_GEOMETRY
|
|
|
458
471
|
BOOL submitted = movement.integerValue == NSReturnTextMovement;
|
|
459
472
|
id<UITextFieldDelegate> delegate = [self uikitCompat_uiDelegate];
|
|
460
473
|
|
|
474
|
+
// AppKit ends editing on Return and then re-establishes the field editor with
|
|
475
|
+
// the text selected, so this runs again on the next click -- a second blur
|
|
476
|
+
// with no focus in between. Report the end once per editing session.
|
|
477
|
+
if (_reportedEndEditing) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
_reportedEndEditing = YES;
|
|
481
|
+
|
|
461
482
|
// Return is a submit before it is an end-of-editing, and the order matters:
|
|
462
483
|
// onSubmitEditing should carry the text, which onBlur may go on to clear.
|
|
484
|
+
// The answer says whether the field should also give up focus: that is
|
|
485
|
+
// `submitBehavior`, which distinguishes `submit` from `blurAndSubmit`.
|
|
486
|
+
BOOL shouldBlurOnSubmit = NO;
|
|
463
487
|
if (submitted && [delegate respondsToSelector:@selector(textFieldShouldReturn:)]) {
|
|
464
|
-
[delegate textFieldShouldReturn:self];
|
|
488
|
+
shouldBlurOnSubmit = [delegate textFieldShouldReturn:self];
|
|
465
489
|
}
|
|
466
490
|
|
|
467
491
|
UIControlEvents events = UIControlEventEditingDidEnd;
|
|
@@ -473,6 +497,17 @@ UIKIT_COMPAT_TEXT_INPUT_GEOMETRY
|
|
|
473
497
|
if ([delegate respondsToSelector:@selector(textFieldDidEndEditing:)]) {
|
|
474
498
|
[delegate textFieldDidEndEditing:self];
|
|
475
499
|
}
|
|
500
|
+
|
|
501
|
+
if (submitted && shouldBlurOnSubmit) {
|
|
502
|
+
// Asynchronously: AppKit is still unwinding this edit, and taking the
|
|
503
|
+
// responder away underneath it leaves a caret drawn in a field that no
|
|
504
|
+
// longer has focus.
|
|
505
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
506
|
+
if (self.currentEditor != nil) {
|
|
507
|
+
[self.window makeFirstResponder:nil];
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
}
|
|
476
511
|
}
|
|
477
512
|
|
|
478
513
|
- (id<UITextDropDelegate>)textDropDelegate
|