react-native-advanced-text 0.1.25 → 0.1.27
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.
- package/android/src/main/java/com/advancedtext/AdvancedTextView.kt +561 -240
- package/android/src/main/java/com/advancedtext/AdvancedTextViewManager.kt +3 -3
- package/lib/module/AdvancedTextViewNativeComponent.ts +26 -26
- package/package.json +1 -1
- package/src/AdvancedTextViewNativeComponent.ts +26 -26
|
@@ -1,316 +1,637 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
1
|
+
#import "AdvancedTextView.h"
|
|
2
|
+
|
|
3
|
+
#import <react/renderer/components/AdvancedTextViewSpec/ComponentDescriptors.h>
|
|
4
|
+
#import <react/renderer/components/AdvancedTextViewSpec/EventEmitters.h>
|
|
5
|
+
#import <react/renderer/components/AdvancedTextViewSpec/Props.h>
|
|
6
|
+
#import <react/renderer/components/AdvancedTextViewSpec/RCTComponentViewHelpers.h>
|
|
7
|
+
|
|
8
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
9
|
+
|
|
10
|
+
using namespace facebook::react;
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@class AdvancedTextView;
|
|
14
|
+
|
|
15
|
+
@interface AdvancedTextView () <RCTAdvancedTextViewViewProtocol, UIGestureRecognizerDelegate, UITextViewDelegate>
|
|
16
|
+
|
|
17
|
+
@property (nonatomic, strong) NSMutableArray<NSDictionary *> *wordRanges;
|
|
18
|
+
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, UIColor *> *highlightColors;
|
|
19
|
+
@property (nonatomic, strong) NSArray<NSString *> *menuOptions;
|
|
20
|
+
@property (nonatomic, assign) NSInteger indicatorWordIndex;
|
|
21
|
+
@property (nonatomic, assign) CGFloat fontSize;
|
|
22
|
+
@property (nonatomic, strong) NSString *fontWeight;
|
|
23
|
+
@property (nonatomic, strong) UIColor *textColor;
|
|
24
|
+
@property (nonatomic, strong) NSString *textAlign;
|
|
25
|
+
@property (nonatomic, strong) NSString *fontFamily;
|
|
26
|
+
|
|
27
|
+
- (void)handleCustomMenuAction:(UIMenuItem *)sender;
|
|
28
|
+
|
|
29
|
+
@end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@interface CustomTextView : UITextView
|
|
33
|
+
@property (nonatomic, weak) AdvancedTextView *parentView;
|
|
34
|
+
@end
|
|
35
|
+
|
|
36
|
+
@implementation CustomTextView
|
|
37
|
+
|
|
38
|
+
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
|
|
39
|
+
{
|
|
40
|
+
NSLog(@"[CustomTextView] canPerformAction: %@", NSStringFromSelector(action));
|
|
41
|
+
|
|
42
|
+
if (action == @selector(handleCustomMenuAction:)) {
|
|
43
|
+
NSLog(@"[CustomTextView] ✅ Allowing custom action");
|
|
44
|
+
return YES;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
NSLog(@"[CustomTextView] ❌ Blocking system action: %@", NSStringFromSelector(action));
|
|
48
|
+
return NO;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
- (void)handleCustomMenuAction:(UIMenuItem *)sender
|
|
52
|
+
{
|
|
53
|
+
if (self.parentView) {
|
|
54
|
+
[self.parentView handleCustomMenuAction:sender];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@end
|
|
59
|
+
|
|
60
|
+
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
menu?.clear()
|
|
62
|
+
@interface AdvancedTextView () <RCTAdvancedTextViewViewProtocol, UIGestureRecognizerDelegate, UITextViewDelegate>
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
val selectionEnd = selectionEnd
|
|
64
|
+
@property (nonatomic, strong) CustomTextView *textView;
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
lastSelectedText = text.subSequence(selectionStart, selectionEnd).toString()
|
|
66
|
+
@end
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
@implementation AdvancedTextView
|
|
69
|
+
|
|
70
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
71
|
+
{
|
|
72
|
+
NSLog(@"[AdvancedTextView] componentDescriptorProvider called");
|
|
73
|
+
return concreteComponentDescriptorProvider<AdvancedTextViewComponentDescriptor>();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
77
|
+
{
|
|
78
|
+
NSLog(@"[AdvancedTextView] initWithFrame called");
|
|
79
|
+
if (self = [super initWithFrame:frame]) {
|
|
80
|
+
@try {
|
|
81
|
+
static const auto defaultProps = std::make_shared<const AdvancedTextViewProps>();
|
|
82
|
+
_props = defaultProps;
|
|
83
|
+
|
|
84
|
+
_wordRanges = [NSMutableArray array];
|
|
85
|
+
_highlightColors = [NSMutableDictionary dictionary];
|
|
86
|
+
_indicatorWordIndex = -1;
|
|
87
|
+
_fontSize = 16.0;
|
|
88
|
+
_fontWeight = @"normal";
|
|
89
|
+
_textColor = [UIColor labelColor];
|
|
90
|
+
_textAlign = @"left";
|
|
91
|
+
_fontFamily = @"System";
|
|
92
|
+
|
|
93
|
+
[self setupTextView];
|
|
94
|
+
[self setupGestureRecognizers];
|
|
95
|
+
|
|
96
|
+
NSLog(@"[AdvancedTextView] Initialization successful");
|
|
97
|
+
} @catch (NSException *exception) {
|
|
98
|
+
NSLog(@"[AdvancedTextView] Exception in init: %@", exception);
|
|
99
|
+
@throw;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
73
102
|
|
|
74
|
-
|
|
75
|
-
|
|
103
|
+
return self;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)setupTextView
|
|
107
|
+
{
|
|
108
|
+
NSLog(@"[AdvancedTextView] setupTextView called");
|
|
109
|
+
@try {
|
|
110
|
+
_textView = [[CustomTextView alloc] initWithFrame:self.bounds];
|
|
111
|
+
_textView.parentView = self;
|
|
112
|
+
_textView.editable = NO;
|
|
113
|
+
_textView.selectable = YES;
|
|
114
|
+
_textView.scrollEnabled = YES;
|
|
115
|
+
_textView.backgroundColor = [UIColor clearColor];
|
|
116
|
+
_textView.textContainerInset = UIEdgeInsetsMake(8, 8, 8, 8);
|
|
117
|
+
_textView.font = [UIFont systemFontOfSize:16];
|
|
118
|
+
_textView.textColor = [UIColor labelColor];
|
|
119
|
+
_textView.delegate = self;
|
|
120
|
+
|
|
121
|
+
self.contentView = _textView;
|
|
122
|
+
NSLog(@"[AdvancedTextView] TextView setup successful");
|
|
123
|
+
} @catch (NSException *exception) {
|
|
124
|
+
NSLog(@"[AdvancedTextView] Exception in setupTextView: %@", exception);
|
|
125
|
+
@throw;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
- (void)setupGestureRecognizers
|
|
130
|
+
{
|
|
131
|
+
NSLog(@"[AdvancedTextView] setupGestureRecognizers called");
|
|
132
|
+
@try {
|
|
133
|
+
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
|
|
134
|
+
initWithTarget:self
|
|
135
|
+
action:@selector(handleTap:)];
|
|
136
|
+
tapGesture.delegate = self;
|
|
137
|
+
[_textView addGestureRecognizer:tapGesture];
|
|
138
|
+
|
|
139
|
+
NSLog(@"[AdvancedTextView] Gesture recognizers setup successful");
|
|
140
|
+
} @catch (NSException *exception) {
|
|
141
|
+
NSLog(@"[AdvancedTextView] Exception in setupGestureRecognizers: %@", exception);
|
|
142
|
+
@throw;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
|
147
|
+
{
|
|
148
|
+
NSLog(@"[AdvancedTextView] updateProps called");
|
|
149
|
+
@try {
|
|
150
|
+
const auto &oldViewProps = *std::static_pointer_cast<AdvancedTextViewProps const>(_props);
|
|
151
|
+
const auto &newViewProps = *std::static_pointer_cast<AdvancedTextViewProps const>(props);
|
|
152
|
+
|
|
153
|
+
BOOL textChanged = NO;
|
|
154
|
+
BOOL highlightsChanged = NO;
|
|
155
|
+
BOOL menuChanged = NO;
|
|
156
|
+
BOOL indicatorChanged = NO;
|
|
157
|
+
BOOL styleChanged = NO;
|
|
158
|
+
|
|
159
|
+
if (oldViewProps.fontSize != newViewProps.fontSize && newViewProps.fontSize) {
|
|
160
|
+
NSLog(@"[AdvancedTextView] Updating fontSize to: %f", newViewProps.fontSize);
|
|
161
|
+
_fontSize = static_cast<CGFloat>(newViewProps.fontSize);
|
|
162
|
+
styleChanged = YES;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (oldViewProps.textAlign != newViewProps.textAlign && !newViewProps.textAlign.empty()) {
|
|
166
|
+
NSLog(@"[AdvancedTextView] Updating textAlign to: %s", newViewProps.textAlign.c_str());
|
|
167
|
+
_textAlign = [NSString stringWithUTF8String:newViewProps.textAlign.c_str()];
|
|
168
|
+
styleChanged = YES;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (oldViewProps.fontWeight != newViewProps.fontWeight && !newViewProps.fontWeight.empty()) {
|
|
172
|
+
NSLog(@"[AdvancedTextView] Updating fontWeight to: %s", newViewProps.fontWeight.c_str());
|
|
173
|
+
_fontWeight = [NSString stringWithUTF8String:newViewProps.fontWeight.c_str()];
|
|
174
|
+
styleChanged = YES;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (oldViewProps.fontFamily != newViewProps.fontFamily && !newViewProps.fontFamily.empty()) {
|
|
178
|
+
NSLog(@"[AdvancedTextView] Updating fontFamily to: %s", newViewProps.fontFamily.c_str());
|
|
179
|
+
_fontFamily = [NSString stringWithUTF8String:newViewProps.fontFamily.c_str()];
|
|
180
|
+
styleChanged = YES;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (oldViewProps.color != newViewProps.color && !newViewProps.color.empty()) {
|
|
184
|
+
NSLog(@"[AdvancedTextView] Updating color to: %s", newViewProps.color.c_str());
|
|
185
|
+
NSString *colorStr = [NSString stringWithUTF8String:newViewProps.color.c_str()];
|
|
186
|
+
_textColor = [self hexStringToColor:colorStr];
|
|
187
|
+
styleChanged = YES;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (oldViewProps.text != newViewProps.text) {
|
|
191
|
+
textChanged = YES;
|
|
192
|
+
NSLog(@"[AdvancedTextView] Text changed");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (oldViewProps.highlightedWords.size() != newViewProps.highlightedWords.size()) {
|
|
196
|
+
highlightsChanged = YES;
|
|
197
|
+
} else {
|
|
198
|
+
for (size_t i = 0; i < oldViewProps.highlightedWords.size(); i++) {
|
|
199
|
+
const auto &oldHW = oldViewProps.highlightedWords[i];
|
|
200
|
+
const auto &newHW = newViewProps.highlightedWords[i];
|
|
201
|
+
if (oldHW.index != newHW.index || oldHW.highlightColor != newHW.highlightColor) {
|
|
202
|
+
highlightsChanged = YES;
|
|
203
|
+
break;
|
|
76
204
|
}
|
|
77
|
-
return false
|
|
78
205
|
}
|
|
206
|
+
}
|
|
79
207
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
208
|
+
if (oldViewProps.menuOptions.size() != newViewProps.menuOptions.size()) {
|
|
209
|
+
menuChanged = YES;
|
|
210
|
+
} else {
|
|
211
|
+
for (size_t i = 0; i < oldViewProps.menuOptions.size(); i++) {
|
|
212
|
+
if (oldViewProps.menuOptions[i] != newViewProps.menuOptions[i]) {
|
|
213
|
+
menuChanged = YES;
|
|
214
|
+
break;
|
|
86
215
|
}
|
|
87
|
-
return false
|
|
88
216
|
}
|
|
217
|
+
}
|
|
89
218
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
219
|
+
if (oldViewProps.indicatorWordIndex != newViewProps.indicatorWordIndex) {
|
|
220
|
+
indicatorChanged = YES;
|
|
93
221
|
}
|
|
94
|
-
}
|
|
95
222
|
|
|
223
|
+
if (textChanged) {
|
|
224
|
+
NSString *text = [NSString stringWithUTF8String:newViewProps.text.c_str()];
|
|
225
|
+
[self updateTextContent:text];
|
|
226
|
+
}
|
|
96
227
|
|
|
228
|
+
if (highlightsChanged) {
|
|
229
|
+
[self updateHighlightedWords:newViewProps.highlightedWords];
|
|
230
|
+
}
|
|
97
231
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
Log.d(TAG, "Text unchanged, skipping update")
|
|
101
|
-
return
|
|
232
|
+
if (menuChanged) {
|
|
233
|
+
[self updateMenuOptions:newViewProps.menuOptions];
|
|
102
234
|
}
|
|
103
235
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
236
|
+
if (indicatorChanged) {
|
|
237
|
+
_indicatorWordIndex = newViewProps.indicatorWordIndex;
|
|
238
|
+
[self updateTextAppearance];
|
|
239
|
+
}
|
|
109
240
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
241
|
+
if (styleChanged) {
|
|
242
|
+
NSLog(@"[AdvancedTextView] Style properties changed, updating appearance");
|
|
243
|
+
[self updateTextAppearance];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
[super updateProps:props oldProps:oldProps];
|
|
247
|
+
NSLog(@"[AdvancedTextView] updateProps completed successfully");
|
|
248
|
+
} @catch (NSException *exception) {
|
|
249
|
+
NSLog(@"[AdvancedTextView] Exception in updateProps: %@", exception.reason);
|
|
250
|
+
@throw;
|
|
113
251
|
}
|
|
252
|
+
}
|
|
114
253
|
|
|
254
|
+
- (void)updateTextContent:(NSString *)text
|
|
255
|
+
{
|
|
256
|
+
NSLog(@"[AdvancedTextView] updateTextContent called with text length: %lu",
|
|
257
|
+
(unsigned long)text.length);
|
|
258
|
+
@try {
|
|
259
|
+
if (!text) {
|
|
260
|
+
NSLog(@"[AdvancedTextView] Text is nil, skipping update");
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
115
263
|
|
|
116
|
-
|
|
117
|
-
if (fontSize == size) return
|
|
118
|
-
fontSize = size
|
|
119
|
-
updateTextWithHighlights() // ensures size change is applied with highlights
|
|
120
|
-
}
|
|
264
|
+
_textView.text = text;
|
|
121
265
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
266
|
+
[_wordRanges removeAllObjects];
|
|
267
|
+
|
|
268
|
+
NSRange searchRange = NSMakeRange(0, text.length);
|
|
269
|
+
NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
|
|
270
|
+
|
|
271
|
+
NSInteger wordIndex = 0;
|
|
272
|
+
while (searchRange.location < text.length) {
|
|
273
|
+
while (searchRange.location < text.length &&
|
|
274
|
+
[whitespaceSet characterIsMember:[text characterAtIndex:searchRange.location]]) {
|
|
275
|
+
searchRange.location++;
|
|
276
|
+
searchRange.length = text.length - searchRange.location;
|
|
277
|
+
}
|
|
126
278
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
279
|
+
if (searchRange.location >= text.length) break;
|
|
280
|
+
|
|
281
|
+
NSUInteger wordStart = searchRange.location;
|
|
282
|
+
while (searchRange.location < text.length &&
|
|
283
|
+
![whitespaceSet characterIsMember:[text characterAtIndex:searchRange.location]]) {
|
|
284
|
+
searchRange.location++;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
NSRange wordRange = NSMakeRange(wordStart, searchRange.location - wordStart);
|
|
288
|
+
NSString *word = [text substringWithRange:wordRange];
|
|
289
|
+
|
|
290
|
+
[_wordRanges addObject:@{
|
|
291
|
+
@"word": word,
|
|
292
|
+
@"range": [NSValue valueWithRange:wordRange],
|
|
293
|
+
@"index": @(wordIndex)
|
|
294
|
+
}];
|
|
295
|
+
|
|
296
|
+
wordIndex++;
|
|
297
|
+
searchRange.length = text.length - searchRange.location;
|
|
135
298
|
}
|
|
136
|
-
}
|
|
137
299
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
300
|
+
NSLog(@"[AdvancedTextView] Parsed %ld words", (long)_wordRanges.count);
|
|
301
|
+
[self updateTextAppearance];
|
|
302
|
+
} @catch (NSException *exception) {
|
|
303
|
+
NSLog(@"[AdvancedTextView] Exception in updateTextContent: %@", exception);
|
|
304
|
+
@throw;
|
|
142
305
|
}
|
|
306
|
+
}
|
|
143
307
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
308
|
+
- (void)updateHighlightedWords:(const std::vector<AdvancedTextViewHighlightedWordsStruct> &)highlightedWords
|
|
309
|
+
{
|
|
310
|
+
NSLog(@"[AdvancedTextView] updateHighlightedWords called with %zu highlights",
|
|
311
|
+
highlightedWords.size());
|
|
312
|
+
@try {
|
|
313
|
+
[_highlightColors removeAllObjects];
|
|
314
|
+
|
|
315
|
+
for (const auto &hw : highlightedWords) {
|
|
316
|
+
NSInteger index = hw.index;
|
|
317
|
+
NSString *colorString = [NSString stringWithUTF8String:hw.highlightColor.c_str()];
|
|
318
|
+
UIColor *color = [self hexStringToColor:colorString];
|
|
148
319
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
320
|
+
if (color) {
|
|
321
|
+
_highlightColors[@(index)] = color;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
[self updateTextAppearance];
|
|
326
|
+
} @catch (NSException *exception) {
|
|
327
|
+
NSLog(@"[AdvancedTextView] Exception in updateHighlightedWords: %@", exception);
|
|
328
|
+
@throw;
|
|
153
329
|
}
|
|
330
|
+
}
|
|
154
331
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
332
|
+
- (void)updateMenuOptions:(const std::vector<std::string> &)options
|
|
333
|
+
{
|
|
334
|
+
NSLog(@"[AdvancedTextView] updateMenuOptions called with %zu options", options.size());
|
|
335
|
+
@try {
|
|
336
|
+
NSMutableArray *menuArray = [NSMutableArray array];
|
|
337
|
+
for (const auto &option : options) {
|
|
338
|
+
NSString *optionStr = [NSString stringWithUTF8String:option.c_str()];
|
|
339
|
+
[menuArray addObject:optionStr];
|
|
340
|
+
NSLog(@"[AdvancedTextView] Added menu option: %@", optionStr);
|
|
341
|
+
}
|
|
342
|
+
_menuOptions = [menuArray copy];
|
|
343
|
+
} @catch (NSException *exception) {
|
|
344
|
+
NSLog(@"[AdvancedTextView] Exception in updateMenuOptions: %@", exception);
|
|
345
|
+
@throw;
|
|
159
346
|
}
|
|
347
|
+
}
|
|
160
348
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
349
|
+
- (void)updateTextAppearance
|
|
350
|
+
{
|
|
351
|
+
@try {
|
|
352
|
+
if (!_textView.text || _textView.text.length == 0) {
|
|
353
|
+
return;
|
|
165
354
|
}
|
|
166
355
|
|
|
167
|
-
|
|
168
|
-
|
|
356
|
+
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]
|
|
357
|
+
initWithString:_textView.text];
|
|
169
358
|
|
|
170
|
-
regex.findAll(text).forEachIndexed { index, match ->
|
|
171
|
-
positions.add(WordPosition(
|
|
172
|
-
index = index,
|
|
173
|
-
start = match.range.first,
|
|
174
|
-
end = match.range.last + 1,
|
|
175
|
-
word = match.value
|
|
176
|
-
))
|
|
177
|
-
}
|
|
178
359
|
|
|
179
|
-
|
|
180
|
-
Log.d(TAG, "Calculated ${wordPositions.size} word positions")
|
|
181
|
-
}
|
|
360
|
+
UIFont *font = nil;
|
|
182
361
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
Log.d(TAG, "No text available, skipping")
|
|
186
|
-
return
|
|
362
|
+
if (_fontFamily && _fontFamily.length > 0) {
|
|
363
|
+
font = [UIFont fontWithName:_fontFamily size:_fontSize > 0 ? _fontSize : 16.0];
|
|
187
364
|
}
|
|
188
365
|
|
|
189
|
-
|
|
366
|
+
if (!font) {
|
|
367
|
+
if (_fontWeight && [_fontWeight.lowercaseString isEqualToString:@"bold"]) {
|
|
368
|
+
font = [UIFont boldSystemFontOfSize:_fontSize > 0 ? _fontSize : 16.0];
|
|
369
|
+
} else if (_fontWeight && [_fontWeight.lowercaseString isEqualToString:@"italic"]) {
|
|
370
|
+
font = [UIFont italicSystemFontOfSize:_fontSize > 0 ? _fontSize : 16.0];
|
|
371
|
+
} else {
|
|
372
|
+
font = [UIFont systemFontOfSize:_fontSize > 0 ? _fontSize : 16.0];
|
|
373
|
+
}
|
|
374
|
+
}
|
|
190
375
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
376
|
+
[attributedString addAttribute:NSFontAttributeName
|
|
377
|
+
value:font
|
|
378
|
+
range:NSMakeRange(0, attributedString.length)];
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
UIColor *color = _textColor ?: [UIColor labelColor];
|
|
382
|
+
[attributedString addAttribute:NSForegroundColorAttributeName
|
|
383
|
+
value:color
|
|
384
|
+
range:NSMakeRange(0, attributedString.length)];
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
for (NSDictionary *wordInfo in _wordRanges) {
|
|
388
|
+
NSNumber *index = wordInfo[@"index"];
|
|
389
|
+
NSValue *rangeValue = wordInfo[@"range"];
|
|
390
|
+
NSRange range = [rangeValue rangeValue];
|
|
391
|
+
|
|
392
|
+
if (range.location + range.length > attributedString.length) {
|
|
393
|
+
continue;
|
|
200
394
|
}
|
|
201
395
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
208
|
-
)
|
|
396
|
+
UIColor *highlightColor = _highlightColors[index];
|
|
397
|
+
if (highlightColor) {
|
|
398
|
+
[attributedString addAttribute:NSBackgroundColorAttributeName
|
|
399
|
+
value:highlightColor
|
|
400
|
+
range:range];
|
|
209
401
|
}
|
|
210
402
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
403
|
+
if (_indicatorWordIndex >= 0 && [index integerValue] == _indicatorWordIndex) {
|
|
404
|
+
UIColor *indicatorColor = [[UIColor systemBlueColor] colorWithAlphaComponent:0.3];
|
|
405
|
+
[attributedString addAttribute:NSBackgroundColorAttributeName
|
|
406
|
+
value:indicatorColor
|
|
407
|
+
range:range];
|
|
408
|
+
}
|
|
217
409
|
}
|
|
218
410
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
"
|
|
223
|
-
|
|
411
|
+
_textView.attributedText = attributedString;
|
|
412
|
+
|
|
413
|
+
if (_textAlign) {
|
|
414
|
+
if ([_textAlign.lowercaseString isEqualToString:@"center"]) {
|
|
415
|
+
_textView.textAlignment = NSTextAlignmentCenter;
|
|
416
|
+
} else if ([_textAlign.lowercaseString isEqualToString:@"right"]) {
|
|
417
|
+
_textView.textAlignment = NSTextAlignmentRight;
|
|
418
|
+
} else {
|
|
419
|
+
_textView.textAlignment = NSTextAlignmentLeft;
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
_textView.textAlignment = NSTextAlignmentLeft;
|
|
224
423
|
}
|
|
225
424
|
|
|
226
|
-
|
|
425
|
+
} @catch (NSException *exception) {
|
|
426
|
+
NSLog(@"[AdvancedTextView] Exception in updateTextAppearance: %@", exception.reason);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
227
430
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
431
|
+
- (void)handleTap:(UITapGestureRecognizer *)gesture
|
|
432
|
+
{
|
|
433
|
+
@try {
|
|
434
|
+
if (gesture.state != UIGestureRecognizerStateEnded) return;
|
|
435
|
+
|
|
436
|
+
CGPoint location = [gesture locationInView:_textView];
|
|
437
|
+
NSInteger wordIndex = [self wordIndexAtPoint:location];
|
|
438
|
+
|
|
439
|
+
_textView.selectedTextRange = nil;
|
|
233
440
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
441
|
+
if (wordIndex >= 0 && wordIndex < _wordRanges.count) {
|
|
442
|
+
NSDictionary *wordInfo = _wordRanges[wordIndex];
|
|
443
|
+
NSString *word = wordInfo[@"word"];
|
|
444
|
+
|
|
445
|
+
[self emitWordPressEvent:word index:wordIndex];
|
|
237
446
|
}
|
|
447
|
+
} @catch (NSException *exception) {
|
|
448
|
+
NSLog(@"[AdvancedTextView] Exception in handleTap: %@", exception);
|
|
238
449
|
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
#pragma mark - UITextViewDelegate
|
|
453
|
+
|
|
454
|
+
- (void)textViewDidChangeSelection:(UITextView *)textView
|
|
455
|
+
{
|
|
456
|
+
NSString *selectedText = [textView.text substringWithRange:textView.selectedRange];
|
|
457
|
+
|
|
458
|
+
if (selectedText.length > 0) {
|
|
459
|
+
NSLog(@"[AdvancedTextView] Selected text: %@", selectedText);
|
|
239
460
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
Color.parseColor(colorString)
|
|
243
|
-
} catch (e: IllegalArgumentException) {
|
|
244
|
-
Log.e(TAG, "Invalid color: $colorString, using yellow")
|
|
245
|
-
Color.YELLOW
|
|
461
|
+
if (_menuOptions && _menuOptions.count > 0) {
|
|
462
|
+
[self setupCustomMenuItems];
|
|
246
463
|
}
|
|
247
464
|
}
|
|
465
|
+
}
|
|
248
466
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
val event = Arguments.createMap().apply {
|
|
253
|
-
putString("selectedText", selectedText)
|
|
254
|
-
putString("event", eventType)
|
|
255
|
-
}
|
|
467
|
+
- (void)setupCustomMenuItems
|
|
468
|
+
{
|
|
469
|
+
NSLog(@"[AdvancedTextView] Setting up %lu custom menu items", (unsigned long)_menuOptions.count);
|
|
256
470
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
471
|
+
UIMenuController *menuController = [UIMenuController sharedMenuController];
|
|
472
|
+
NSMutableArray *customItems = [NSMutableArray array];
|
|
473
|
+
|
|
474
|
+
for (NSString *option in _menuOptions) {
|
|
475
|
+
UIMenuItem *item = [[UIMenuItem alloc] initWithTitle:option
|
|
476
|
+
action:@selector(handleCustomMenuAction:)];
|
|
477
|
+
[customItems addObject:item];
|
|
478
|
+
NSLog(@"[AdvancedTextView] Created menu item: %@", option);
|
|
262
479
|
}
|
|
263
480
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
private val word: String
|
|
267
|
-
) : ClickableSpan() {
|
|
481
|
+
menuController.menuItems = customItems;
|
|
482
|
+
}
|
|
268
483
|
|
|
269
|
-
override fun onClick(widget: View) {
|
|
270
|
-
Log.d(TAG, "WordClickableSpan onClick triggered: '$word' (index=$wordIndex)")
|
|
271
484
|
|
|
272
|
-
|
|
273
|
-
|
|
485
|
+
- (void)handleCustomMenuAction:(UIMenuItem *)sender
|
|
486
|
+
{
|
|
487
|
+
NSLog(@"[AdvancedTextView] Custom menu action: %@", sender.title);
|
|
488
|
+
|
|
489
|
+
NSString *selectedText = [_textView.text substringWithRange:_textView.selectedRange];
|
|
490
|
+
|
|
491
|
+
[self emitSelectionEvent:selectedText menuOption:sender.title];
|
|
492
|
+
|
|
493
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
494
|
+
self->_textView.selectedTextRange = nil;
|
|
495
|
+
NSLog(@"[AdvancedTextView] Selection cleared");
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
- (NSInteger)wordIndexAtPoint:(CGPoint)point
|
|
500
|
+
{
|
|
501
|
+
@try {
|
|
502
|
+
if (!_textView.layoutManager || !_textView.textContainer) {
|
|
503
|
+
return -1;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
point.x -= _textView.textContainerInset.left;
|
|
507
|
+
point.y -= _textView.textContainerInset.top;
|
|
508
|
+
|
|
509
|
+
NSLayoutManager *layoutManager = _textView.layoutManager;
|
|
510
|
+
NSTextContainer *textContainer = _textView.textContainer;
|
|
511
|
+
|
|
512
|
+
NSUInteger characterIndex = [layoutManager characterIndexForPoint:point
|
|
513
|
+
inTextContainer:textContainer
|
|
514
|
+
fractionOfDistanceBetweenInsertionPoints:nil];
|
|
515
|
+
|
|
516
|
+
for (NSDictionary *wordInfo in _wordRanges) {
|
|
517
|
+
NSValue *rangeValue = wordInfo[@"range"];
|
|
518
|
+
NSRange range = [rangeValue rangeValue];
|
|
519
|
+
|
|
520
|
+
if (NSLocationInRange(characterIndex, range)) {
|
|
521
|
+
return [wordInfo[@"index"] integerValue];
|
|
274
522
|
}
|
|
275
523
|
}
|
|
276
524
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
525
|
+
return -1;
|
|
526
|
+
} @catch (NSException *exception) {
|
|
527
|
+
return -1;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
- (void)setFontSize:(CGFloat)fontSize {
|
|
532
|
+
_fontSize = fontSize;
|
|
533
|
+
[self updateTextAppearance];
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
- (void)setFontWeight:(NSString *)fontWeight {
|
|
537
|
+
_fontWeight = fontWeight;
|
|
538
|
+
[self updateTextAppearance];
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
- (void)setTextColor:(UIColor *)textColor {
|
|
542
|
+
_textColor = textColor;
|
|
543
|
+
[self updateTextAppearance];
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
- (void)setTextAlign:(NSString *)textAlign {
|
|
547
|
+
_textAlign = textAlign;
|
|
548
|
+
[self updateTextAppearance];
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
- (void)setFontFamily:(NSString *)fontFamily {
|
|
552
|
+
_fontFamily = fontFamily;
|
|
553
|
+
[self updateTextAppearance];
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
- (void)emitWordPressEvent:(NSString *)word index:(NSInteger)index
|
|
557
|
+
{
|
|
558
|
+
NSLog(@"[AdvancedTextView] emitWordPressEvent: %@ at index: %ld", word, (long)index);
|
|
559
|
+
@try {
|
|
560
|
+
if (_eventEmitter) {
|
|
561
|
+
auto emitter = std::static_pointer_cast<const AdvancedTextViewEventEmitter>(_eventEmitter);
|
|
562
|
+
|
|
563
|
+
AdvancedTextViewEventEmitter::OnWordPress event;
|
|
564
|
+
event.word = [word UTF8String];
|
|
565
|
+
event.index = static_cast<int>(index);
|
|
566
|
+
|
|
567
|
+
emitter->onWordPress(event);
|
|
281
568
|
}
|
|
569
|
+
} @catch (NSException *exception) {
|
|
570
|
+
NSLog(@"[AdvancedTextView] Exception in emitWordPressEvent: %@", exception);
|
|
282
571
|
}
|
|
572
|
+
}
|
|
283
573
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
574
|
+
- (void)emitSelectionEvent:(NSString *)selectedText menuOption:(NSString *)option
|
|
575
|
+
{
|
|
576
|
+
NSLog(@"[AdvancedTextView] emitSelectionEvent: %@ with option: %@", selectedText, option);
|
|
577
|
+
@try {
|
|
578
|
+
if (_eventEmitter) {
|
|
579
|
+
auto emitter = std::static_pointer_cast<const AdvancedTextViewEventEmitter>(_eventEmitter);
|
|
291
580
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
581
|
+
AdvancedTextViewEventEmitter::OnSelection event;
|
|
582
|
+
event.selectedText = [selectedText UTF8String];
|
|
583
|
+
event.event = [option UTF8String];
|
|
584
|
+
|
|
585
|
+
emitter->onSelection(event);
|
|
296
586
|
}
|
|
587
|
+
} @catch (NSException *exception) {
|
|
588
|
+
NSLog(@"[AdvancedTextView] Exception in emitSelectionEvent: %@", exception);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
- (void)layoutSubviews
|
|
593
|
+
{
|
|
594
|
+
@try {
|
|
595
|
+
[super layoutSubviews];
|
|
596
|
+
_textView.frame = self.bounds;
|
|
597
|
+
} @catch (NSException *exception) {
|
|
598
|
+
NSLog(@"[AdvancedTextView] Exception in layoutSubviews: %@", exception);
|
|
297
599
|
}
|
|
600
|
+
}
|
|
298
601
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
602
|
+
- (UIColor *)hexStringToColor:(NSString *)stringToConvert
|
|
603
|
+
{
|
|
604
|
+
@try {
|
|
605
|
+
if (!stringToConvert || [stringToConvert length] == 0) {
|
|
606
|
+
return nil;
|
|
302
607
|
}
|
|
608
|
+
|
|
609
|
+
NSString *noHashString = [stringToConvert stringByReplacingOccurrencesOfString:@"#" withString:@""];
|
|
610
|
+
NSScanner *stringScanner = [NSScanner scannerWithString:noHashString];
|
|
611
|
+
|
|
612
|
+
unsigned hex;
|
|
613
|
+
if (![stringScanner scanHexInt:&hex]) {
|
|
614
|
+
return nil;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
int r = (hex >> 16) & 0xFF;
|
|
618
|
+
int g = (hex >> 8) & 0xFF;
|
|
619
|
+
int b = (hex) & 0xFF;
|
|
620
|
+
|
|
621
|
+
return [UIColor colorWithRed:r / 255.0f green:g / 255.0f blue:b / 255.0f alpha:1.0f];
|
|
622
|
+
} @catch (NSException *exception) {
|
|
623
|
+
return nil;
|
|
303
624
|
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
Class<RCTComponentViewProtocol> AdvancedTextViewCls(void)
|
|
628
|
+
{
|
|
629
|
+
return AdvancedTextView.class;
|
|
630
|
+
}
|
|
304
631
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
val end: Int,
|
|
309
|
-
val word: String
|
|
310
|
-
)
|
|
632
|
+
- (void)dealloc
|
|
633
|
+
{
|
|
634
|
+
NSLog(@"[AdvancedTextView] dealloc called");
|
|
311
635
|
}
|
|
312
636
|
|
|
313
|
-
|
|
314
|
-
val index: Int,
|
|
315
|
-
val highlightColor: String
|
|
316
|
-
)
|
|
637
|
+
@end
|
|
@@ -83,11 +83,11 @@ class AdvancedTextViewManager : SimpleViewManager<AdvancedTextView>() {
|
|
|
83
83
|
view?.setIndicatorWordIndex(if (index >= 0) index else -1)
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
@ReactProp(name = "color"
|
|
87
|
-
fun setColor(view: AdvancedTextView?, color:
|
|
86
|
+
@ReactProp(name = "color")
|
|
87
|
+
fun setColor(view: AdvancedTextView?, color: String?) {
|
|
88
88
|
android.util.Log.d(NAME, "setColor called with: $color")
|
|
89
89
|
if (color != null) {
|
|
90
|
-
view?.setAdvancedTextColor(color)
|
|
90
|
+
view?.setAdvancedTextColor(Color.parseColor(color))
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
/* eslint-disable prettier/prettier */
|
|
2
|
-
import type { ViewProps } from 'react-native';
|
|
3
|
-
import { codegenNativeComponent } from 'react-native';
|
|
4
|
-
// @ts-ignore
|
|
5
|
-
import type { DirectEventHandler, Int32 } from 'react-native/Libraries/Types/CodegenTypes';
|
|
6
|
-
|
|
7
|
-
interface HighlightedWord {
|
|
8
|
-
index: Int32;
|
|
9
|
-
highlightColor: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface NativeProps extends ViewProps {
|
|
13
|
-
text: string;
|
|
14
|
-
highlightedWords?: ReadonlyArray<HighlightedWord>;
|
|
15
|
-
menuOptions?: ReadonlyArray<string>;
|
|
16
|
-
onWordPress?: DirectEventHandler<{ word: string; index: Int32 }>;
|
|
17
|
-
onSelection?: DirectEventHandler<{ selectedText: string; event: string }>;
|
|
18
|
-
indicatorWordIndex?: Int32;
|
|
19
|
-
fontSize?: Int32;
|
|
20
|
-
fontWeight?: string;
|
|
21
|
-
color?: string;
|
|
22
|
-
textAlign?: string;
|
|
23
|
-
fontFamily?: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default codegenNativeComponent<NativeProps>('AdvancedTextView');
|
|
1
|
+
/* eslint-disable prettier/prettier */
|
|
2
|
+
import type { ViewProps } from 'react-native';
|
|
3
|
+
import { codegenNativeComponent } from 'react-native';
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
import type { DirectEventHandler, Int32 } from 'react-native/Libraries/Types/CodegenTypes';
|
|
6
|
+
|
|
7
|
+
interface HighlightedWord {
|
|
8
|
+
index: Int32;
|
|
9
|
+
highlightColor: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface NativeProps extends ViewProps {
|
|
13
|
+
text: string;
|
|
14
|
+
highlightedWords?: ReadonlyArray<HighlightedWord>;
|
|
15
|
+
menuOptions?: ReadonlyArray<string>;
|
|
16
|
+
onWordPress?: DirectEventHandler<{ word: string; index: Int32 }>;
|
|
17
|
+
onSelection?: DirectEventHandler<{ selectedText: string; event: string }>;
|
|
18
|
+
indicatorWordIndex?: Int32;
|
|
19
|
+
fontSize?: Int32;
|
|
20
|
+
fontWeight?: string;
|
|
21
|
+
color?: string;
|
|
22
|
+
textAlign?: string;
|
|
23
|
+
fontFamily?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default codegenNativeComponent<NativeProps>('AdvancedTextView');
|
package/package.json
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
/* eslint-disable prettier/prettier */
|
|
2
|
-
import type { ViewProps } from 'react-native';
|
|
3
|
-
import { codegenNativeComponent } from 'react-native';
|
|
4
|
-
// @ts-ignore
|
|
5
|
-
import type { DirectEventHandler, Int32 } from 'react-native/Libraries/Types/CodegenTypes';
|
|
6
|
-
|
|
7
|
-
interface HighlightedWord {
|
|
8
|
-
index: Int32;
|
|
9
|
-
highlightColor: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface NativeProps extends ViewProps {
|
|
13
|
-
text: string;
|
|
14
|
-
highlightedWords?: ReadonlyArray<HighlightedWord>;
|
|
15
|
-
menuOptions?: ReadonlyArray<string>;
|
|
16
|
-
onWordPress?: DirectEventHandler<{ word: string; index: Int32 }>;
|
|
17
|
-
onSelection?: DirectEventHandler<{ selectedText: string; event: string }>;
|
|
18
|
-
indicatorWordIndex?: Int32;
|
|
19
|
-
fontSize?: Int32;
|
|
20
|
-
fontWeight?: string;
|
|
21
|
-
color?: string;
|
|
22
|
-
textAlign?: string;
|
|
23
|
-
fontFamily?: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default codegenNativeComponent<NativeProps>('AdvancedTextView');
|
|
1
|
+
/* eslint-disable prettier/prettier */
|
|
2
|
+
import type { ViewProps } from 'react-native';
|
|
3
|
+
import { codegenNativeComponent } from 'react-native';
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
import type { DirectEventHandler, Int32 } from 'react-native/Libraries/Types/CodegenTypes';
|
|
6
|
+
|
|
7
|
+
interface HighlightedWord {
|
|
8
|
+
index: Int32;
|
|
9
|
+
highlightColor: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface NativeProps extends ViewProps {
|
|
13
|
+
text: string;
|
|
14
|
+
highlightedWords?: ReadonlyArray<HighlightedWord>;
|
|
15
|
+
menuOptions?: ReadonlyArray<string>;
|
|
16
|
+
onWordPress?: DirectEventHandler<{ word: string; index: Int32 }>;
|
|
17
|
+
onSelection?: DirectEventHandler<{ selectedText: string; event: string }>;
|
|
18
|
+
indicatorWordIndex?: Int32;
|
|
19
|
+
fontSize?: Int32;
|
|
20
|
+
fontWeight?: string;
|
|
21
|
+
color?: string;
|
|
22
|
+
textAlign?: string;
|
|
23
|
+
fontFamily?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default codegenNativeComponent<NativeProps>('AdvancedTextView');
|