react-native-advanced-text 0.1.34 → 0.1.40

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/README.md CHANGED
@@ -14,12 +14,11 @@ npm install react-native-advanced-text
14
14
 
15
15
 
16
16
  ```js
17
- import { AdvancedTextView } from "react-native-advanced-text";
17
+ import { AdvancedText } from "react-native-advanced-text";
18
18
 
19
19
  <AdvancedText
20
20
  text={'This is an example of AdvancedText component. Tap on any word to see the event in action.'}
21
21
  style={[styles.AdvancedText, { minHeight }]}
22
- indicatorWordIndex={2}
23
22
  onWordPress={(event) => {
24
23
  console.log({event})
25
24
  }}
@@ -28,9 +27,15 @@ import { AdvancedTextView } from "react-native-advanced-text";
28
27
  console.log({event})
29
28
  }}
30
29
  highlightedWords={[
30
+ {
31
+ index: 2,
32
+ highlightColor: '#FFD60A',
33
+ borderRadius: 10,
34
+ },
31
35
  {
32
36
  index: 4,
33
37
  highlightColor: '#6baeffb5',
38
+ borderRadius: 6,
34
39
  },
35
40
  ]}
36
41
  fontSize={24}
@@ -1,16 +1,16 @@
1
1
  package com.advancedtext
2
2
 
3
3
  import android.content.Context
4
+ import android.graphics.Canvas
4
5
  import android.graphics.Color
5
6
  import android.graphics.Point
7
+ import android.graphics.RectF
6
8
  import android.text.SpannableString
7
9
  import android.text.Spannable
8
10
  import android.text.Spanned
9
11
  import android.text.TextPaint
10
12
  import android.text.method.ArrowKeyMovementMethod
11
13
  import android.text.style.ClickableSpan
12
- import android.text.style.BackgroundColorSpan
13
- import android.text.style.ForegroundColorSpan
14
14
  import android.util.AttributeSet
15
15
  import android.util.Log
16
16
  import android.view.ActionMode
@@ -32,7 +32,6 @@ class AdvancedTextView : TextView {
32
32
 
33
33
  private var highlightedWords: List<HighlightedWord> = emptyList()
34
34
  private var menuOptions: List<String> = emptyList()
35
- private var indicatorWordIndex: Int = -1
36
35
  private var lastSelectedText: String = ""
37
36
  private var customActionMode: ActionMode? = null
38
37
  private var currentText: String = ""
@@ -43,6 +42,9 @@ class AdvancedTextView : TextView {
43
42
  private var fontFamily: String = "sans-serif"
44
43
  private var lineHeightMultiplier: Float = 1.0f
45
44
 
45
+ private var indicatorWordIndex: Int = -1
46
+ private var indicatorColor: String = ""
47
+
46
48
  private var wordPositions: List<WordPosition> = emptyList()
47
49
 
48
50
  constructor(context: Context?) : super(context) { init() }
@@ -157,18 +159,24 @@ class AdvancedTextView : TextView {
157
159
  this.menuOptions = menuOptions
158
160
  }
159
161
 
162
+ fun setIndicatorWordIndex(index: Int) {
163
+ if (indicatorWordIndex == index) return
164
+ indicatorWordIndex = index
165
+ invalidate()
166
+ }
167
+
168
+ fun setIndicatorColor(color: String) {
169
+ if (indicatorColor == color) return
170
+ indicatorColor = color
171
+ invalidate()
172
+ }
173
+
160
174
  fun setHighlightedWords(highlightedWords: List<HighlightedWord>) {
161
175
  if (this.highlightedWords == highlightedWords) return
162
176
  this.highlightedWords = highlightedWords
163
177
  updateTextWithHighlights()
164
178
  }
165
179
 
166
- fun setIndicatorWordIndex(index: Int) {
167
- if (this.indicatorWordIndex == index) return
168
- this.indicatorWordIndex = index
169
- updateTextWithHighlights()
170
- }
171
-
172
180
  private fun calculateWordPositions(text: String) {
173
181
  if (text.isEmpty()) {
174
182
  wordPositions = emptyList()
@@ -206,27 +214,12 @@ class AdvancedTextView : TextView {
206
214
  val spannableString = SpannableString(currentText)
207
215
 
208
216
  wordPositions.forEach { wordPos ->
209
- highlightedWords.find { it.index == wordPos.index }?.let { highlightedWord ->
210
- val color = parseColor(highlightedWord.highlightColor)
211
- spannableString.setSpan(
212
- BackgroundColorSpan(color),
213
- wordPos.start,
214
- wordPos.extendedEnd,
215
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
216
- )
217
- }
218
-
219
- if (wordPos.index == indicatorWordIndex) {
220
- spannableString.setSpan(
221
- ForegroundColorSpan(Color.parseColor(textColor)),
222
- wordPos.start,
223
- wordPos.end,
224
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
225
- )
226
- }
227
-
228
217
  spannableString.setSpan(
229
- WordClickableSpan(wordPos.index, wordPos.word),
218
+ WordClickableSpan(
219
+ wordIndex = wordPos.index,
220
+ word = wordPos.word,
221
+ wordColor = parseColor(textColor)
222
+ ),
230
223
  wordPos.start,
231
224
  wordPos.end,
232
225
  Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
@@ -258,6 +251,90 @@ class AdvancedTextView : TextView {
258
251
  }
259
252
  }
260
253
 
254
+ override fun onDraw(canvas: Canvas) {
255
+ drawHighlightedWordBackgrounds(canvas)
256
+ super.onDraw(canvas)
257
+ }
258
+
259
+ private fun drawHighlightedWordBackgrounds(canvas: Canvas) {
260
+ val currentLayout = layout ?: return
261
+ val density = resources.displayMetrics.density
262
+ val horizontalPadding = 6f * density
263
+ val verticalPadding = 2f * density
264
+ val originalColor = paint.color
265
+
266
+ highlightedWords.forEach { highlightedWord ->
267
+ val wordPos = wordPositions.find { it.index == highlightedWord.index } ?: return@forEach
268
+ val start = wordPos.start
269
+ val end = wordPos.extendedEnd.coerceAtMost(currentText.length)
270
+
271
+ if (start >= end) return@forEach
272
+
273
+ val startLine = currentLayout.getLineForOffset(start)
274
+ val safeEndOffset = (end - 1).coerceAtLeast(start)
275
+ val endLine = currentLayout.getLineForOffset(safeEndOffset)
276
+
277
+ paint.color = parseColor(highlightedWord.highlightColor)
278
+
279
+ for (line in startLine..endLine) {
280
+ val lineStartOffset = maxOf(start, currentLayout.getLineStart(line))
281
+ val lineEndOffset = minOf(end, currentLayout.getLineEnd(line))
282
+ if (lineStartOffset >= lineEndOffset) continue
283
+
284
+ val left = currentLayout.getPrimaryHorizontal(lineStartOffset)
285
+ val right = currentLayout.getPrimaryHorizontal(lineEndOffset)
286
+ val top = currentLayout.getLineTop(line).toFloat()
287
+ val bottom = currentLayout.getLineBottom(line).toFloat()
288
+ val rect = RectF(
289
+ totalPaddingLeft + left - horizontalPadding,
290
+ totalPaddingTop + top + verticalPadding,
291
+ totalPaddingLeft + right + horizontalPadding,
292
+ totalPaddingTop + bottom - verticalPadding
293
+ )
294
+ val radius = highlightedWord.borderRadius * density
295
+ canvas.drawRoundRect(rect, radius, radius, paint)
296
+ }
297
+ }
298
+
299
+ // Draw indicator for indicatorWordIndex
300
+ if (indicatorWordIndex >= 0 && indicatorColor.isNotEmpty()) {
301
+ val wordPos = wordPositions.find { it.index == indicatorWordIndex }
302
+ if (wordPos != null) {
303
+ val start = wordPos.start
304
+ val end = wordPos.extendedEnd.coerceAtMost(currentText.length)
305
+
306
+ if (start < end) {
307
+ val startLine = currentLayout.getLineForOffset(start)
308
+ val safeEndOffset = (end - 1).coerceAtLeast(start)
309
+ val endLine = currentLayout.getLineForOffset(safeEndOffset)
310
+
311
+ paint.color = parseColor(indicatorColor)
312
+
313
+ for (line in startLine..endLine) {
314
+ val lineStartOffset = maxOf(start, currentLayout.getLineStart(line))
315
+ val lineEndOffset = minOf(end, currentLayout.getLineEnd(line))
316
+ if (lineStartOffset >= lineEndOffset) continue
317
+
318
+ val left = currentLayout.getPrimaryHorizontal(lineStartOffset)
319
+ val right = currentLayout.getPrimaryHorizontal(lineEndOffset)
320
+ val top = currentLayout.getLineTop(line).toFloat()
321
+ val bottom = currentLayout.getLineBottom(line).toFloat()
322
+ val rect = RectF(
323
+ totalPaddingLeft + left - horizontalPadding,
324
+ totalPaddingTop + top + verticalPadding,
325
+ totalPaddingLeft + right + horizontalPadding,
326
+ totalPaddingTop + bottom - verticalPadding
327
+ )
328
+ val radius = 4f * density
329
+ canvas.drawRoundRect(rect, radius, radius, paint)
330
+ }
331
+ }
332
+ }
333
+ }
334
+
335
+ paint.color = originalColor
336
+ }
337
+
261
338
  private fun parseColor(colorString: String): Int {
262
339
  return try {
263
340
  Color.parseColor(colorString)
@@ -284,7 +361,8 @@ class AdvancedTextView : TextView {
284
361
 
285
362
  private inner class WordClickableSpan(
286
363
  private val wordIndex: Int,
287
- private val word: String
364
+ private val word: String,
365
+ private val wordColor: Int
288
366
  ) : ClickableSpan() {
289
367
 
290
368
  override fun onClick(widget: View) {
@@ -295,7 +373,7 @@ class AdvancedTextView : TextView {
295
373
  override fun updateDrawState(ds: TextPaint) {
296
374
  super.updateDrawState(ds)
297
375
  ds.isUnderlineText = false
298
- ds.color = Color.parseColor(textColor)
376
+ ds.color = wordColor
299
377
  }
300
378
  }
301
379
 
@@ -381,5 +459,6 @@ class AdvancedTextView : TextView {
381
459
 
382
460
  data class HighlightedWord(
383
461
  val index: Int,
384
- val highlightColor: String
462
+ val highlightColor: String,
463
+ val borderRadius: Float = 0f
385
464
  )
@@ -2,7 +2,6 @@
2
2
  package com.advancedtext
3
3
 
4
4
  import android.graphics.Color
5
- import android.util.TypedValue
6
5
  import android.view.ViewGroup
7
6
  import com.facebook.react.bridge.ReadableArray
8
7
  import com.facebook.react.module.annotations.ReactModule
@@ -50,7 +49,12 @@ class AdvancedTextViewManager : SimpleViewManager<AdvancedTextView>() {
50
49
  words.add(
51
50
  HighlightedWord(
52
51
  index = wordMap.getInt("index"),
53
- highlightColor = wordMap.getString("highlightColor") ?: "#FFFF00"
52
+ highlightColor = wordMap.getString("highlightColor") ?: "#FFFF00",
53
+ borderRadius = if (wordMap.hasKey("borderRadius")) {
54
+ wordMap.getDouble("borderRadius").toFloat()
55
+ } else {
56
+ 0f
57
+ }
54
58
  )
55
59
  )
56
60
  }
@@ -77,12 +81,6 @@ class AdvancedTextViewManager : SimpleViewManager<AdvancedTextView>() {
77
81
  view?.setMenuOptions(options)
78
82
  }
79
83
 
80
- @ReactProp(name = "indicatorWordIndex")
81
- fun setIndicatorWordIndex(view: AdvancedTextView?, index: Int) {
82
- android.util.Log.d(NAME, "setIndicatorWordIndex: $index")
83
- view?.setIndicatorWordIndex(if (index >= 0) index else -1)
84
- }
85
-
86
84
  @ReactProp(name = "color")
87
85
  fun setColor(view: AdvancedTextView?, color: String?) {
88
86
  android.util.Log.d(NAME, "setColor called with: $color")
@@ -124,6 +122,20 @@ class AdvancedTextViewManager : SimpleViewManager<AdvancedTextView>() {
124
122
  }
125
123
 
126
124
 
125
+ @ReactProp(name = "indicatorWordIndex")
126
+ fun setIndicatorWordIndex(view: AdvancedTextView?, indicatorWordIndex: Int) {
127
+ android.util.Log.d(NAME, "setIndicatorWordIndex called with: $indicatorWordIndex")
128
+ view?.setIndicatorWordIndex(indicatorWordIndex)
129
+ }
130
+
131
+ @ReactProp(name = "indicatorColor")
132
+ fun setIndicatorColor(view: AdvancedTextView?, indicatorColor: String?) {
133
+ android.util.Log.d(NAME, "setIndicatorColor called with: $indicatorColor")
134
+ if (indicatorColor != null) {
135
+ view?.setIndicatorColor(indicatorColor)
136
+ }
137
+ }
138
+
127
139
  @ReactProp(name = "lineHeight")
128
140
  fun setLineHeight(view: AdvancedTextView?, lineHeight: Float) {
129
141
  android.util.Log.d(NAME, "setLineHeight called with: $lineHeight")
@@ -15,17 +15,19 @@ using namespace facebook::react;
15
15
  @interface AdvancedTextView () <RCTAdvancedTextViewViewProtocol, UIGestureRecognizerDelegate, UITextViewDelegate>
16
16
 
17
17
  @property (nonatomic, strong) NSMutableArray<NSDictionary *> *wordRanges;
18
- @property (nonatomic, strong) NSMutableDictionary<NSNumber *, UIColor *> *highlightColors;
18
+ @property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSDictionary *> *highlightStyles;
19
19
  @property (nonatomic, strong) NSArray<NSString *> *menuOptions;
20
- @property (nonatomic, assign) NSInteger indicatorWordIndex;
21
20
  @property (nonatomic, assign) CGFloat fontSize;
22
21
  @property (nonatomic, strong) NSString *fontWeight;
23
22
  @property (nonatomic, strong) UIColor *textColor;
24
23
  @property (nonatomic, strong) NSString *textAlign;
25
24
  @property (nonatomic, strong) NSString *fontFamily;
26
25
  @property (nonatomic, assign) CGFloat lineHeight;
26
+ @property (nonatomic, assign) NSInteger indicatorWordIndex;
27
+ @property (nonatomic, strong) UIColor *indicatorColor;
27
28
 
28
29
  - (void)handleCustomMenuAction:(UIMenuItem *)sender;
30
+ - (void)drawHighlightedBackgroundsInTextView:(UITextView *)textView;
29
31
 
30
32
  @end
31
33
 
@@ -56,6 +58,12 @@ using namespace facebook::react;
56
58
  }
57
59
  }
58
60
 
61
+ - (void)drawRect:(CGRect)rect
62
+ {
63
+ [self.parentView drawHighlightedBackgroundsInTextView:self];
64
+ [super drawRect:rect];
65
+ }
66
+
59
67
  @end
60
68
 
61
69
 
@@ -83,14 +91,15 @@ using namespace facebook::react;
83
91
  _props = defaultProps;
84
92
 
85
93
  _wordRanges = [NSMutableArray array];
86
- _highlightColors = [NSMutableDictionary dictionary];
87
- _indicatorWordIndex = -1;
94
+ _highlightStyles = [NSMutableDictionary dictionary];
88
95
  _fontSize = 16.0;
89
96
  _fontWeight = @"normal";
90
97
  _textColor = [UIColor labelColor];
91
98
  _textAlign = @"left";
92
99
  _fontFamily = @"System";
93
100
  _lineHeight = 0.0;
101
+ _indicatorWordIndex = -1;
102
+ _indicatorColor = nil;
94
103
 
95
104
  [self setupTextView];
96
105
  [self setupGestureRecognizers];
@@ -155,7 +164,6 @@ using namespace facebook::react;
155
164
  BOOL textChanged = NO;
156
165
  BOOL highlightsChanged = NO;
157
166
  BOOL menuChanged = NO;
158
- BOOL indicatorChanged = NO;
159
167
  BOOL styleChanged = NO;
160
168
 
161
169
  if (oldViewProps.fontSize != newViewProps.fontSize && newViewProps.fontSize) {
@@ -200,7 +208,9 @@ using namespace facebook::react;
200
208
  for (size_t i = 0; i < oldViewProps.highlightedWords.size(); i++) {
201
209
  const auto &oldHW = oldViewProps.highlightedWords[i];
202
210
  const auto &newHW = newViewProps.highlightedWords[i];
203
- if (oldHW.index != newHW.index || oldHW.highlightColor != newHW.highlightColor) {
211
+ if (oldHW.index != newHW.index ||
212
+ oldHW.highlightColor != newHW.highlightColor ||
213
+ oldHW.borderRadius != newHW.borderRadius) {
204
214
  highlightsChanged = YES;
205
215
  break;
206
216
  }
@@ -218,16 +228,29 @@ using namespace facebook::react;
218
228
  }
219
229
  }
220
230
 
221
- if (oldViewProps.indicatorWordIndex != newViewProps.indicatorWordIndex) {
222
- indicatorChanged = YES;
223
- }
224
-
225
231
  if (oldViewProps.lineHeight != newViewProps.lineHeight) {
226
232
  NSLog(@"[AdvancedTextView] Updating lineHeight to: %f", newViewProps.lineHeight);
227
233
  _lineHeight = static_cast<CGFloat>(newViewProps.lineHeight);
228
234
  styleChanged = YES;
229
235
  }
230
236
 
237
+ if (oldViewProps.indicatorWordIndex != newViewProps.indicatorWordIndex) {
238
+ NSLog(@"[AdvancedTextView] Updating indicatorWordIndex to: %d", newViewProps.indicatorWordIndex);
239
+ _indicatorWordIndex = static_cast<NSInteger>(newViewProps.indicatorWordIndex);
240
+ [_textView setNeedsDisplay];
241
+ }
242
+
243
+ if (oldViewProps.indicatorColor != newViewProps.indicatorColor) {
244
+ NSLog(@"[AdvancedTextView] Updating indicatorColor");
245
+ if (!newViewProps.indicatorColor.empty()) {
246
+ NSString *colorStr = [NSString stringWithUTF8String:newViewProps.indicatorColor.c_str()];
247
+ _indicatorColor = [self hexStringToColor:colorStr];
248
+ } else {
249
+ _indicatorColor = nil;
250
+ }
251
+ [_textView setNeedsDisplay];
252
+ }
253
+
231
254
  if (textChanged) {
232
255
  NSString *text = [NSString stringWithUTF8String:newViewProps.text.c_str()];
233
256
  [self updateTextContent:text];
@@ -241,11 +264,6 @@ using namespace facebook::react;
241
264
  [self updateMenuOptions:newViewProps.menuOptions];
242
265
  }
243
266
 
244
- if (indicatorChanged) {
245
- _indicatorWordIndex = newViewProps.indicatorWordIndex;
246
- [self updateTextAppearance];
247
- }
248
-
249
267
  if (styleChanged) {
250
268
  NSLog(@"[AdvancedTextView] Style properties changed, updating appearance");
251
269
  [self updateTextAppearance];
@@ -339,15 +357,19 @@ using namespace facebook::react;
339
357
  NSLog(@"[AdvancedTextView] updateHighlightedWords called with %zu highlights",
340
358
  highlightedWords.size());
341
359
  @try {
342
- [_highlightColors removeAllObjects];
360
+ [_highlightStyles removeAllObjects];
343
361
 
344
362
  for (const auto &hw : highlightedWords) {
345
363
  NSInteger index = hw.index;
346
364
  NSString *colorString = [NSString stringWithUTF8String:hw.highlightColor.c_str()];
347
365
  UIColor *color = [self hexStringToColor:colorString];
366
+ CGFloat borderRadius = static_cast<CGFloat>(hw.borderRadius);
348
367
 
349
368
  if (color) {
350
- _highlightColors[@(index)] = color;
369
+ _highlightStyles[@(index)] = @{
370
+ @"color": color,
371
+ @"borderRadius": @(MAX(borderRadius, 0.0))
372
+ };
351
373
  }
352
374
  }
353
375
 
@@ -430,37 +452,8 @@ using namespace facebook::react;
430
452
  value:color
431
453
  range:NSMakeRange(0, attributedString.length)];
432
454
 
433
-
434
- for (NSDictionary *wordInfo in _wordRanges) {
435
- NSNumber *index = wordInfo[@"index"];
436
- NSValue *rangeValue = wordInfo[@"range"];
437
- NSRange range = [rangeValue rangeValue];
438
-
439
- if (range.location + range.length > attributedString.length) {
440
- continue;
441
- }
442
-
443
- UIColor *highlightColor = _highlightColors[index];
444
- if (highlightColor) {
445
- NSValue *extendedRangeValue = wordInfo[@"extendedRange"];
446
- NSRange extendedRange = extendedRangeValue ? [extendedRangeValue rangeValue] : range;
447
-
448
- if (extendedRange.location + extendedRange.length <= attributedString.length) {
449
- [attributedString addAttribute:NSBackgroundColorAttributeName
450
- value:highlightColor
451
- range:extendedRange];
452
- }
453
- }
454
-
455
- if (_indicatorWordIndex >= 0 && [index integerValue] == _indicatorWordIndex) {
456
- UIColor *indicatorColor = [[UIColor systemBlueColor] colorWithAlphaComponent:0.3];
457
- [attributedString addAttribute:NSBackgroundColorAttributeName
458
- value:indicatorColor
459
- range:range];
460
- }
461
- }
462
-
463
455
  _textView.attributedText = attributedString;
456
+ [_textView setNeedsDisplay];
464
457
 
465
458
  if (_textAlign) {
466
459
  if ([_textAlign.lowercaseString isEqualToString:@"center"]) {
@@ -479,6 +472,81 @@ using namespace facebook::react;
479
472
  }
480
473
  }
481
474
 
475
+ - (void)drawHighlightedBackgroundsInTextView:(UITextView *)textView
476
+ {
477
+ if (!textView.layoutManager || !textView.textContainer) {
478
+ return;
479
+ }
480
+
481
+ NSLayoutManager *layoutManager = textView.layoutManager;
482
+ NSTextContainer *textContainer = textView.textContainer;
483
+
484
+ for (NSDictionary *wordInfo in _wordRanges) {
485
+ NSNumber *index = wordInfo[@"index"];
486
+ NSDictionary *highlightStyle = _highlightStyles[index];
487
+ if (!highlightStyle) {
488
+ continue;
489
+ }
490
+
491
+ NSValue *extendedRangeValue = wordInfo[@"extendedRange"];
492
+ NSRange characterRange = extendedRangeValue ? [extendedRangeValue rangeValue] : [wordInfo[@"range"] rangeValue];
493
+ if (characterRange.location == NSNotFound || characterRange.length == 0) {
494
+ continue;
495
+ }
496
+
497
+ UIColor *highlightColor = highlightStyle[@"color"];
498
+ CGFloat radius = [highlightStyle[@"borderRadius"] doubleValue];
499
+ NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:characterRange actualCharacterRange:nil];
500
+
501
+ [highlightColor setFill];
502
+ [layoutManager enumerateEnclosingRectsForGlyphRange:glyphRange
503
+ withinSelectedGlyphRange:NSMakeRange(NSNotFound, 0)
504
+ inTextContainer:textContainer
505
+ usingBlock:^(CGRect enclosingRect, BOOL *stop) {
506
+ CGRect adjustedRect = CGRectInset(enclosingRect, -6.0, -2.0);
507
+ adjustedRect.origin.x += textView.textContainerInset.left;
508
+ adjustedRect.origin.y += textView.textContainerInset.top;
509
+
510
+ UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:adjustedRect
511
+ cornerRadius:MAX(radius, 0.0)];
512
+ [path fill];
513
+ }];
514
+ }
515
+
516
+ // Draw indicator for indicatorWordIndex
517
+ if (_indicatorWordIndex >= 0 && _indicatorColor) {
518
+ for (NSDictionary *wordInfo in _wordRanges) {
519
+ NSNumber *index = wordInfo[@"index"];
520
+ if ([index integerValue] != _indicatorWordIndex) {
521
+ continue;
522
+ }
523
+
524
+ NSValue *extendedRangeValue = wordInfo[@"extendedRange"];
525
+ NSRange characterRange = extendedRangeValue ? [extendedRangeValue rangeValue] : [wordInfo[@"range"] rangeValue];
526
+ if (characterRange.location == NSNotFound || characterRange.length == 0) {
527
+ break;
528
+ }
529
+
530
+ NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:characterRange actualCharacterRange:nil];
531
+
532
+ [_indicatorColor setFill];
533
+ [layoutManager enumerateEnclosingRectsForGlyphRange:glyphRange
534
+ withinSelectedGlyphRange:NSMakeRange(NSNotFound, 0)
535
+ inTextContainer:textContainer
536
+ usingBlock:^(CGRect enclosingRect, BOOL *stop) {
537
+ CGRect adjustedRect = CGRectInset(enclosingRect, -6.0, -2.0);
538
+ adjustedRect.origin.x += textView.textContainerInset.left;
539
+ adjustedRect.origin.y += textView.textContainerInset.top;
540
+
541
+ UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:adjustedRect
542
+ cornerRadius:4.0];
543
+ [path fill];
544
+ }];
545
+ break;
546
+ }
547
+ }
548
+ }
549
+
482
550
 
483
551
  - (void)handleTap:(UITapGestureRecognizer *)gesture
484
552
  {
@@ -10,7 +10,6 @@ export const AdvancedText = ({
10
10
  menuOptions,
11
11
  onWordPress,
12
12
  onSelection,
13
- indicatorWordIndex,
14
13
  ...restProps
15
14
  }) => {
16
15
  return /*#__PURE__*/_jsx(AdvancedTextViewNativeComponent, {
@@ -20,8 +19,7 @@ export const AdvancedText = ({
20
19
  highlightedWords: highlightedWords,
21
20
  menuOptions: menuOptions,
22
21
  onWordPress: onWordPress,
23
- onSelection: onSelection,
24
- indicatorWordIndex: indicatorWordIndex
22
+ onSelection: onSelection
25
23
  });
26
24
  };
27
25
  //# sourceMappingURL=AdvancedText.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","AdvancedTextViewNativeComponent","jsx","_jsx","AdvancedText","text","style","highlightedWords","menuOptions","onWordPress","onSelection","indicatorWordIndex","restProps"],"sourceRoot":"../../src","sources":["AdvancedText.tsx"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,OAAOC,+BAA+B,MAE/B,mCAAmC;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAE3C,OAAO,MAAMC,YAAmC,GAAGA,CAAC;EAClDC,IAAI;EACJC,KAAK;EACLC,gBAAgB;EAChBC,WAAW;EACXC,WAAW;EACXC,WAAW;EACXC,kBAAkB;EAClB,GAAGC;AACL,CAAC,KAAK;EACJ,oBACET,IAAA,CAACF,+BAA+B;IAAA,GAC1BW,SAAS;IACbN,KAAK,EAAEA,KAAM;IACbD,IAAI,EAAEA,IAAK;IACXE,gBAAgB,EAAEA,gBAAiB;IACnCC,WAAW,EAAEA,WAAY;IACzBC,WAAW,EAAEA,WAAY;IACzBC,WAAW,EAAEA,WAAY;IACzBC,kBAAkB,EAAEA;EAAmB,CACxC,CAAC;AAEN,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["React","AdvancedTextViewNativeComponent","jsx","_jsx","AdvancedText","text","style","highlightedWords","menuOptions","onWordPress","onSelection","restProps"],"sourceRoot":"../../src","sources":["AdvancedText.tsx"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,OAAOC,+BAA+B,MAE/B,mCAAmC;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAE3C,OAAO,MAAMC,YAAmC,GAAGA,CAAC;EAClDC,IAAI;EACJC,KAAK;EACLC,gBAAgB;EAChBC,WAAW;EACXC,WAAW;EACXC,WAAW;EACX,GAAGC;AACL,CAAC,KAAK;EACJ,oBACER,IAAA,CAACF,+BAA+B;IAAA,GAC1BU,SAAS;IACbL,KAAK,EAAEA,KAAM;IACbD,IAAI,EAAEA,IAAK;IACXE,gBAAgB,EAAEA,gBAAiB;IACnCC,WAAW,EAAEA,WAAY;IACzBC,WAAW,EAAEA,WAAY;IACzBC,WAAW,EAAEA;EAAY,CAC1B,CAAC;AAEN,CAAC","ignoreList":[]}
@@ -7,6 +7,7 @@ import type { DirectEventHandler, Int32 , Float } from 'react-native/Libraries/
7
7
  interface HighlightedWord {
8
8
  index: Int32;
9
9
  highlightColor: string;
10
+ borderRadius?: Float;
10
11
  }
11
12
 
12
13
  export interface NativeProps extends ViewProps {
@@ -15,13 +16,14 @@ export interface NativeProps extends ViewProps {
15
16
  menuOptions?: ReadonlyArray<string>;
16
17
  onWordPress?: DirectEventHandler<{ word: string; index: Int32 }>;
17
18
  onSelection?: DirectEventHandler<{ selectedText: string; event: string }>;
18
- indicatorWordIndex?: Int32;
19
19
  fontSize?: Int32;
20
20
  fontWeight?: string;
21
21
  color?: string;
22
22
  textAlign?: string;
23
23
  fontFamily?: string;
24
24
  lineHeight?: Float;
25
+ indicatorWordIndex?: Int32;
26
+ indicatorColor?: string;
25
27
  }
26
28
 
27
29
  export default codegenNativeComponent<NativeProps>('AdvancedTextView');
@@ -1 +1 @@
1
- {"version":3,"file":"AdvancedText.d.ts","sourceRoot":"","sources":["../../../src/AdvancedText.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAwC,EACtC,KAAK,WAAW,EACjB,MAAM,mCAAmC,CAAC;AAE3C,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAsB9C,CAAC"}
1
+ {"version":3,"file":"AdvancedText.d.ts","sourceRoot":"","sources":["../../../src/AdvancedText.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAwC,EACtC,KAAK,WAAW,EACjB,MAAM,mCAAmC,CAAC;AAE3C,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAoB9C,CAAC"}
@@ -3,6 +3,7 @@ import type { DirectEventHandler, Int32, Float } from 'react-native/Libraries/Ty
3
3
  interface HighlightedWord {
4
4
  index: Int32;
5
5
  highlightColor: string;
6
+ borderRadius?: Float;
6
7
  }
7
8
  export interface NativeProps extends ViewProps {
8
9
  text: string;
@@ -16,13 +17,14 @@ export interface NativeProps extends ViewProps {
16
17
  selectedText: string;
17
18
  event: string;
18
19
  }>;
19
- indicatorWordIndex?: Int32;
20
20
  fontSize?: Int32;
21
21
  fontWeight?: string;
22
22
  color?: string;
23
23
  textAlign?: string;
24
24
  fontFamily?: string;
25
25
  lineHeight?: Float;
26
+ indicatorWordIndex?: Int32;
27
+ indicatorColor?: string;
26
28
  }
27
29
  declare const _default: import("react-native/types_generated/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeProps>;
28
30
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"AdvancedTextViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/AdvancedTextViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAG,KAAK,EAAG,MAAM,2CAA2C,CAAC;AAEpG,UAAU,eAAe;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAClD,WAAW,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,kBAAkB,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;IACjE,WAAW,CAAC,EAAE,kBAAkB,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,kBAAkB,CAAC,EAAE,KAAK,CAAC;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,KAAK,CAAC;CACpB;;AAED,wBAAuE"}
1
+ {"version":3,"file":"AdvancedTextViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/AdvancedTextViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAG,KAAK,EAAG,MAAM,2CAA2C,CAAC;AAEpG,UAAU,eAAe;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAClD,WAAW,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,kBAAkB,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;IACjE,WAAW,CAAC,EAAE,kBAAkB,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,KAAK,CAAC;IACnB,kBAAkB,CAAC,EAAE,KAAK,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;;AAED,wBAAuE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-advanced-text",
3
- "version": "0.1.34",
3
+ "version": "0.1.40",
4
4
  "description": " Advanced text component for React Native with custom select options.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -10,7 +10,6 @@ export const AdvancedText: React.FC<NativeProps> = ({
10
10
  menuOptions,
11
11
  onWordPress,
12
12
  onSelection,
13
- indicatorWordIndex,
14
13
  ...restProps
15
14
  }) => {
16
15
  return (
@@ -22,7 +21,6 @@ export const AdvancedText: React.FC<NativeProps> = ({
22
21
  menuOptions={menuOptions}
23
22
  onWordPress={onWordPress}
24
23
  onSelection={onSelection}
25
- indicatorWordIndex={indicatorWordIndex}
26
24
  />
27
25
  );
28
26
  };
@@ -7,6 +7,7 @@ import type { DirectEventHandler, Int32 , Float } from 'react-native/Libraries/
7
7
  interface HighlightedWord {
8
8
  index: Int32;
9
9
  highlightColor: string;
10
+ borderRadius?: Float;
10
11
  }
11
12
 
12
13
  export interface NativeProps extends ViewProps {
@@ -15,13 +16,14 @@ export interface NativeProps extends ViewProps {
15
16
  menuOptions?: ReadonlyArray<string>;
16
17
  onWordPress?: DirectEventHandler<{ word: string; index: Int32 }>;
17
18
  onSelection?: DirectEventHandler<{ selectedText: string; event: string }>;
18
- indicatorWordIndex?: Int32;
19
19
  fontSize?: Int32;
20
20
  fontWeight?: string;
21
21
  color?: string;
22
22
  textAlign?: string;
23
23
  fontFamily?: string;
24
24
  lineHeight?: Float;
25
+ indicatorWordIndex?: Int32;
26
+ indicatorColor?: string;
25
27
  }
26
28
 
27
29
  export default codegenNativeComponent<NativeProps>('AdvancedTextView');