react-native-highlight-text-view 0.1.8 → 0.1.10

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
@@ -47,11 +47,11 @@ export default function App() {
47
47
  | `color` | `string` | `#FFFF00` | Background highlight color (hex format) |
48
48
  | `textColor` | `string` | - | Text color (hex format) |
49
49
  | `textAlign` | `string` | `left` | Text alignment. Supports: `'left'`, `'center'`, `'right'`, `'justify'`, `'flex-start'`, `'flex-end'`, `'top'`, `'bottom'`, `'top-left'`, `'top-center'`, `'top-right'`, `'bottom-left'`, `'bottom-center'`, `'bottom-right'` |
50
- | `verticalAlign` | `'top' \| 'center' \| 'middle' \| 'bottom'` | - | Vertical alignment (iOS only). Alternative to using combined `textAlign` values |
50
+ | `verticalAlign` | `'top' \| 'center' \| 'middle' \| 'bottom'` | - | Vertical alignment (iOS only). Alternative to using combined `textAlign` values. **Note:** Android does not support vertical alignment and will use default vertical positioning. |
51
51
  | `fontFamily` | `string` | - | Font family name |
52
52
  | `fontSize` | `string` | `32` | Font size in points |
53
- | `lineHeight` | `string` | - | Line height override |
54
- | `highlightBorderRadius` | `string` | `4` | Border radius for the highlight background |
53
+ | `lineHeight` | `string` | `0` | Line height override (0 means use default line height) |
54
+ | `highlightBorderRadius` | `string` | `0` | Border radius for the highlight background |
55
55
  | `padding` | `string` | `4` | Padding around each character highlight (expands background outward) |
56
56
  | `paddingLeft` | `string` | - | Left padding for character highlight |
57
57
  | `paddingRight` | `string` | - | Right padding for character highlight |
@@ -5,6 +5,7 @@ import android.graphics.Canvas
5
5
  import android.graphics.Color
6
6
  import android.graphics.Paint
7
7
  import android.graphics.RectF
8
+ import android.graphics.Typeface
8
9
  import android.text.Editable
9
10
  import android.text.Spannable
10
11
  import android.text.SpannableString
@@ -146,8 +147,9 @@ class HighlightTextView : AppCompatEditText {
146
147
  private var characterBackgroundColor: Int = Color.parseColor("#FFFF00")
147
148
  private var textColorValue: Int = Color.BLACK
148
149
  private var cornerRadius: Float = 4f
149
- private var charPaddingLeft: Float = 8f
150
- private var charPaddingRight: Float = 8f
150
+ private var highlightBorderRadius: Float = 0f
151
+ private var charPaddingLeft: Float = 4f
152
+ private var charPaddingRight: Float = 4f
151
153
  private var charPaddingTop: Float = 4f
152
154
  private var charPaddingBottom: Float = 4f
153
155
  private var backgroundInsetTop: Float = 0f
@@ -155,6 +157,9 @@ class HighlightTextView : AppCompatEditText {
155
157
  private var backgroundInsetLeft: Float = 0f
156
158
  private var backgroundInsetRight: Float = 0f
157
159
  private var customLineHeight: Float = 0f
160
+ private var currentFontFamily: String? = null
161
+ private var currentFontWeight: String = "normal"
162
+ private var currentVerticalAlign: String? = null
158
163
  private var isUpdatingText: Boolean = false
159
164
 
160
165
  var onTextChangeListener: ((String) -> Unit)? = null
@@ -243,6 +248,61 @@ class HighlightTextView : AppCompatEditText {
243
248
  applyCharacterBackgrounds()
244
249
  }
245
250
 
251
+ fun setHighlightBorderRadius(radius: Float) {
252
+ highlightBorderRadius = radius
253
+ applyCharacterBackgrounds()
254
+ }
255
+
256
+ fun setFontWeight(weight: String) {
257
+ currentFontWeight = weight
258
+ updateFont()
259
+ }
260
+
261
+ fun setFontFamilyProp(family: String?) {
262
+ currentFontFamily = family
263
+ updateFont()
264
+ }
265
+
266
+ private fun updateFont() {
267
+ val style = when (currentFontWeight) {
268
+ "bold", "700", "800", "900" -> Typeface.BOLD
269
+ "100", "200", "300" -> Typeface.NORMAL // Android doesn't have lighter than normal
270
+ else -> Typeface.NORMAL
271
+ }
272
+
273
+ val typeface = if (currentFontFamily != null) {
274
+ when (currentFontFamily?.lowercase()) {
275
+ "system" -> Typeface.create(Typeface.DEFAULT, style)
276
+ "sans-serif" -> Typeface.create(Typeface.SANS_SERIF, style)
277
+ "serif" -> Typeface.create(Typeface.SERIF, style)
278
+ "monospace" -> Typeface.create(Typeface.MONOSPACE, style)
279
+ else -> Typeface.create(currentFontFamily, style)
280
+ }
281
+ } else {
282
+ Typeface.create(Typeface.DEFAULT, style)
283
+ }
284
+
285
+ this.typeface = typeface
286
+ applyCharacterBackgrounds()
287
+ }
288
+
289
+ fun setVerticalAlign(align: String?) {
290
+ currentVerticalAlign = align
291
+ updateVerticalAlignment()
292
+ }
293
+
294
+ private fun updateVerticalAlignment() {
295
+ // Preserve horizontal alignment when updating vertical
296
+ val horizontalGravity = gravity and Gravity.HORIZONTAL_GRAVITY_MASK
297
+ val verticalGravity = when (currentVerticalAlign) {
298
+ "top" -> Gravity.TOP
299
+ "bottom" -> Gravity.BOTTOM
300
+ else -> Gravity.CENTER_VERTICAL
301
+ }
302
+
303
+ gravity = horizontalGravity or verticalGravity
304
+ }
305
+
246
306
  fun setBackgroundInsetTop(inset: Float) {
247
307
  backgroundInsetTop = inset
248
308
  applyCharacterBackgrounds()
@@ -310,6 +370,9 @@ class HighlightTextView : AppCompatEditText {
310
370
  val isFirst = i == 0 || !shouldHighlightChar(text, i - 1)
311
371
  val isLast = i == text.length - 1 || !shouldHighlightChar(text, i + 1)
312
372
 
373
+ // Use highlightBorderRadius if specified, otherwise use cornerRadius (matches iOS)
374
+ val radius = if (highlightBorderRadius > 0) highlightBorderRadius else cornerRadius
375
+
313
376
  val span = RoundedBackgroundSpan(
314
377
  characterBackgroundColor,
315
378
  textColorValue,
@@ -321,7 +384,7 @@ class HighlightTextView : AppCompatEditText {
321
384
  backgroundInsetBottom,
322
385
  backgroundInsetLeft,
323
386
  backgroundInsetRight,
324
- cornerRadius,
387
+ radius,
325
388
  isFirst,
326
389
  isLast
327
390
  )
@@ -1,6 +1,7 @@
1
1
  package com.highlighttext
2
2
 
3
3
  import android.graphics.Color
4
+ import android.graphics.Typeface
4
5
  import android.text.InputType
5
6
  import android.view.Gravity
6
7
  import com.facebook.react.bridge.Arguments
@@ -74,33 +75,54 @@ class HighlightTextViewManager : SimpleViewManager<HighlightTextView>(),
74
75
  override fun setTextAlign(view: HighlightTextView?, value: String?) {
75
76
  // Parse combined alignment (e.g., "top-left", "bottom-center")
76
77
  val parts = value?.split("-") ?: emptyList()
78
+ var verticalAlign: String? = null
77
79
  var horizontalAlign = value
78
80
 
79
81
  if (parts.size == 2) {
80
- // Combined format: use the second part for horizontal alignment
82
+ // Combined format: "top-left", "bottom-center", etc.
83
+ verticalAlign = parts[0]
81
84
  horizontalAlign = parts[1]
85
+ } else if (value == "top" || value == "bottom") {
86
+ // Pure vertical alignment
87
+ verticalAlign = value
88
+ horizontalAlign = null
82
89
  }
83
90
 
84
- // Apply horizontal alignment
85
- view?.gravity = when (horizontalAlign) {
86
- "left", "flex-start" -> Gravity.START or Gravity.CENTER_VERTICAL
87
- "right", "flex-end" -> Gravity.END or Gravity.CENTER_VERTICAL
88
- "center" -> Gravity.CENTER
89
- "justify" -> Gravity.START or Gravity.CENTER_VERTICAL // Android doesn't support justify natively
90
- else -> Gravity.CENTER
91
+ // Determine vertical gravity
92
+ val vGravity = when (verticalAlign) {
93
+ "top" -> Gravity.TOP
94
+ "bottom" -> Gravity.BOTTOM
95
+ else -> Gravity.CENTER_VERTICAL
91
96
  }
97
+
98
+ // Determine horizontal gravity
99
+ val hGravity = when (horizontalAlign) {
100
+ "left", "flex-start" -> Gravity.START
101
+ "right", "flex-end" -> Gravity.END
102
+ "center" -> Gravity.CENTER_HORIZONTAL
103
+ "justify" -> Gravity.START // Android doesn't support justify natively
104
+ else -> Gravity.CENTER_HORIZONTAL
105
+ }
106
+
107
+ // Apply combined gravity
108
+ view?.gravity = vGravity or hGravity
92
109
  }
93
110
 
94
111
  @ReactProp(name = "verticalAlign")
95
112
  override fun setVerticalAlign(view: HighlightTextView?, value: String?) {
96
- // Android EditText doesn't support vertical alignment as easily as iOS
97
- // This would require custom implementation with layout adjustments
98
- // For now, we'll keep the default behavior
113
+ view?.setVerticalAlign(value)
99
114
  }
100
115
 
101
116
  @ReactProp(name = "fontFamily")
102
117
  override fun setFontFamily(view: HighlightTextView?, value: String?) {
103
- // Font family handling can be added if needed
118
+ view?.setFontFamilyProp(value)
119
+ }
120
+
121
+ @ReactProp(name = "fontWeight")
122
+ override fun setFontWeight(view: HighlightTextView?, value: String?) {
123
+ value?.let { weight ->
124
+ view?.setFontWeight(weight)
125
+ }
104
126
  }
105
127
 
106
128
  @ReactProp(name = "fontSize")
@@ -155,7 +177,7 @@ class HighlightTextViewManager : SimpleViewManager<HighlightTextView>(),
155
177
  @ReactProp(name = "highlightBorderRadius")
156
178
  override fun setHighlightBorderRadius(view: HighlightTextView?, value: String?) {
157
179
  value?.toFloatOrNull()?.let { radius ->
158
- view?.setCornerRadius(radius)
180
+ view?.setHighlightBorderRadius(radius)
159
181
  }
160
182
  }
161
183
 
@@ -89,6 +89,8 @@ using namespace facebook::react;
89
89
  CGFloat _backgroundInsetLeft;
90
90
  CGFloat _backgroundInsetRight;
91
91
  CGFloat _lineHeight;
92
+ NSString * _fontFamily;
93
+ NSString * _fontWeight;
92
94
  BOOL _isUpdatingText;
93
95
  NSString * _currentVerticalAlignment;
94
96
  NSTextAlignment _currentHorizontalAlignment;
@@ -118,6 +120,8 @@ using namespace facebook::react;
118
120
  _backgroundInsetLeft = 0.0;
119
121
  _backgroundInsetRight = 0.0;
120
122
  _lineHeight = 0.0; // 0 means use default line height
123
+ _fontFamily = nil;
124
+ _fontWeight = @"normal";
121
125
  _currentVerticalAlignment = nil;
122
126
  _currentHorizontalAlignment = NSTextAlignmentCenter;
123
127
 
@@ -276,9 +280,7 @@ using namespace facebook::react;
276
280
  NSString *fontSizeStr = [[NSString alloc] initWithUTF8String: newViewProps.fontSize.c_str()];
277
281
  CGFloat fontSize = [fontSizeStr floatValue];
278
282
  if (fontSize > 0) {
279
- NSString *fontFamily = _textView.font.familyName;
280
- _textView.font = [UIFont fontWithName:fontFamily size:fontSize] ?: [UIFont systemFontOfSize:fontSize];
281
- [self applyCharacterBackgrounds]; // Reapply to update font
283
+ [self updateFont];
282
284
  }
283
285
  }
284
286
 
@@ -302,9 +304,13 @@ using namespace facebook::react;
302
304
  }
303
305
 
304
306
  if (oldViewProps.fontFamily != newViewProps.fontFamily) {
305
- NSString *fontFamily = [[NSString alloc] initWithUTF8String: newViewProps.fontFamily.c_str()];
306
- CGFloat fontSize = _textView.font.pointSize;
307
- _textView.font = [UIFont fontWithName:fontFamily size:fontSize] ?: [UIFont systemFontOfSize:fontSize];
307
+ _fontFamily = [[NSString alloc] initWithUTF8String: newViewProps.fontFamily.c_str()];
308
+ [self updateFont];
309
+ }
310
+
311
+ if (oldViewProps.fontWeight != newViewProps.fontWeight) {
312
+ _fontWeight = [[NSString alloc] initWithUTF8String: newViewProps.fontWeight.c_str()];
313
+ [self updateFont];
308
314
  }
309
315
 
310
316
  if (oldViewProps.padding != newViewProps.padding) {
@@ -451,6 +457,60 @@ Class<RCTComponentViewProtocol> HighlightTextViewCls(void)
451
457
  }
452
458
  }
453
459
 
460
+ - (void)updateFont
461
+ {
462
+ CGFloat fontSize = _textView.font.pointSize;
463
+ UIFont *newFont = nil;
464
+
465
+ // Parse font weight
466
+ UIFontWeight fontWeight = UIFontWeightRegular;
467
+ if (_fontWeight) {
468
+ if ([_fontWeight isEqualToString:@"bold"] || [_fontWeight isEqualToString:@"700"]) {
469
+ fontWeight = UIFontWeightBold;
470
+ } else if ([_fontWeight isEqualToString:@"100"]) {
471
+ fontWeight = UIFontWeightUltraLight;
472
+ } else if ([_fontWeight isEqualToString:@"200"]) {
473
+ fontWeight = UIFontWeightThin;
474
+ } else if ([_fontWeight isEqualToString:@"300"]) {
475
+ fontWeight = UIFontWeightLight;
476
+ } else if ([_fontWeight isEqualToString:@"400"] || [_fontWeight isEqualToString:@"normal"]) {
477
+ fontWeight = UIFontWeightRegular;
478
+ } else if ([_fontWeight isEqualToString:@"500"]) {
479
+ fontWeight = UIFontWeightMedium;
480
+ } else if ([_fontWeight isEqualToString:@"600"]) {
481
+ fontWeight = UIFontWeightSemibold;
482
+ } else if ([_fontWeight isEqualToString:@"700"]) {
483
+ fontWeight = UIFontWeightBold;
484
+ } else if ([_fontWeight isEqualToString:@"800"]) {
485
+ fontWeight = UIFontWeightHeavy;
486
+ } else if ([_fontWeight isEqualToString:@"900"]) {
487
+ fontWeight = UIFontWeightBlack;
488
+ }
489
+ }
490
+
491
+ if (_fontFamily && _fontFamily.length > 0) {
492
+ // Try to get custom font with weight
493
+ UIFontDescriptor *fontDescriptor = [UIFontDescriptor fontDescriptorWithName:_fontFamily size:fontSize];
494
+ UIFontDescriptor *weightedDescriptor = [fontDescriptor fontDescriptorByAddingAttributes:@{
495
+ UIFontDescriptorTraitsAttribute: @{
496
+ UIFontWeightTrait: @(fontWeight)
497
+ }
498
+ }];
499
+ newFont = [UIFont fontWithDescriptor:weightedDescriptor size:fontSize];
500
+
501
+ // Fallback if custom font not found
502
+ if (!newFont) {
503
+ newFont = [UIFont systemFontOfSize:fontSize weight:fontWeight];
504
+ }
505
+ } else {
506
+ // Use system font with weight
507
+ newFont = [UIFont systemFontOfSize:fontSize weight:fontWeight];
508
+ }
509
+
510
+ _textView.font = newFont;
511
+ [self applyCharacterBackgrounds];
512
+ }
513
+
454
514
  - (void)applyCharacterBackgrounds
455
515
  {
456
516
  NSString *text = _textView.text;
@@ -46,6 +46,7 @@ export interface HighlightTextViewProps extends ViewProps {
46
46
  verticalAlign?: string;
47
47
  fontFamily?: string;
48
48
  fontSize?: string;
49
+ fontWeight?: string;
49
50
  lineHeight?: string;
50
51
  highlightBorderRadius?: string;
51
52
  padding?: string;
@@ -28,6 +28,7 @@ export interface HighlightTextViewProps extends ViewProps {
28
28
  verticalAlign?: string;
29
29
  fontFamily?: string;
30
30
  fontSize?: string;
31
+ fontWeight?: string;
31
32
  lineHeight?: string;
32
33
  highlightBorderRadius?: string;
33
34
  padding?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"HighlightTextViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/HighlightTextViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEtF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,OAAO,GACP,SAAS,GACT,YAAY,GACZ,UAAU,GACV,KAAK,GACL,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,WAAW,GACX,aAAa,GACb,eAAe,GACf,cAAc,CAAC;AAEnB,MAAM,WAAW,sBAAuB,SAAQ,SAAS;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oFAAoF;IACpF,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gFAAgF;IAChF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;CACpD;;AAED,wBAEE"}
1
+ {"version":3,"file":"HighlightTextViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/HighlightTextViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEtF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,OAAO,GACP,SAAS,GACT,YAAY,GACZ,UAAU,GACV,KAAK,GACL,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,WAAW,GACX,aAAa,GACb,eAAe,GACf,cAAc,CAAC;AAEnB,MAAM,WAAW,sBAAuB,SAAQ,SAAS;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oFAAoF;IACpF,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gFAAgF;IAChF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;CACpD;;AAED,wBAEE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-highlight-text-view",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "A native text input for React Native that supports inline text highlighting",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -46,6 +46,7 @@ export interface HighlightTextViewProps extends ViewProps {
46
46
  verticalAlign?: string;
47
47
  fontFamily?: string;
48
48
  fontSize?: string;
49
+ fontWeight?: string;
49
50
  lineHeight?: string;
50
51
  highlightBorderRadius?: string;
51
52
  padding?: string;