react-native-highlight-text-view 0.1.1 → 0.1.3

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
@@ -12,13 +12,55 @@ npm install react-native-highlight-text
12
12
 
13
13
  ## Usage
14
14
 
15
-
16
15
  ```js
17
- import { HighlightTextView } from "react-native-highlight-text";
18
-
19
- // ...
16
+ import { useState } from 'react';
17
+ import { HighlightTextView } from 'react-native-highlight-text-view';
18
+
19
+ export default function App() {
20
+ const [text, setText] = useState('Hello World');
21
+
22
+ return (
23
+ <HighlightTextView
24
+ color="#00A4A3"
25
+ textColor="#000000"
26
+ textAlign="flex-start"
27
+ fontSize="32"
28
+ paddingLeft="8"
29
+ paddingRight="8"
30
+ paddingTop="4"
31
+ paddingBottom="4"
32
+ text={text}
33
+ isEditable={true}
34
+ onChange={(e) => {
35
+ setText(e.nativeEvent.text);
36
+ }}
37
+ style={{ width: '100%', height: 200 }}
38
+ />
39
+ );
40
+ }
41
+ ```
20
42
 
21
- <HighlightTextView color="tomato" />
43
+ ## Props
44
+
45
+ | Prop | Type | Default | Description |
46
+ |------|------|---------|-------------|
47
+ | `color` | `string` | `#FFFF00` | Background highlight color (hex format) |
48
+ | `textColor` | `string` | - | Text color (hex format) |
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 |
51
+ | `fontFamily` | `string` | - | Font family name |
52
+ | `fontSize` | `string` | `32` | Font size in points |
53
+ | `padding` | `string` | `4` | Padding around each character highlight |
54
+ | `paddingLeft` | `string` | - | Left padding for character highlight |
55
+ | `paddingRight` | `string` | - | Right padding for character highlight |
56
+ | `paddingTop` | `string` | - | Top padding for character highlight |
57
+ | `paddingBottom` | `string` | - | Bottom padding for character highlight |
58
+ | `text` | `string` | - | Controlled text value |
59
+ | `isEditable` | `boolean` | `true` | Whether the text is editable |
60
+ | `onChange` | `(event: { nativeEvent: { text: string } }) => void` | - | Callback fired when text changes |
61
+
62
+
63
+ **Note:** Vertical alignment is currently supported on iOS only. On Android, text will use default vertical positioning.
22
64
  ```
23
65
 
24
66
 
@@ -73,6 +73,7 @@ using namespace facebook::react;
73
73
  CGFloat _paddingTop;
74
74
  CGFloat _paddingBottom;
75
75
  CGFloat _cornerRadius;
76
+ BOOL _isUpdatingText;
76
77
  }
77
78
 
78
79
  + (ComponentDescriptorProvider)componentDescriptorProvider
@@ -146,13 +147,54 @@ using namespace facebook::react;
146
147
 
147
148
  if (oldViewProps.textAlign != newViewProps.textAlign) {
148
149
  NSString *alignment = [[NSString alloc] initWithUTF8String: newViewProps.textAlign.c_str()];
149
- if ([alignment isEqualToString:@"center"]) {
150
- _textView.textAlignment = NSTextAlignmentCenter;
151
- } else if ([alignment isEqualToString:@"right"]) {
152
- _textView.textAlignment = NSTextAlignmentRight;
150
+
151
+ // Parse combined alignment (e.g., "top-left", "bottom-center")
152
+ NSArray *parts = [alignment componentsSeparatedByString:@"-"];
153
+ NSString *verticalPart = nil;
154
+ NSString *horizontalPart = nil;
155
+
156
+ if (parts.count == 2) {
157
+ // Combined format: "top-left", "bottom-center", etc.
158
+ verticalPart = parts[0];
159
+ horizontalPart = parts[1];
153
160
  } else {
154
- _textView.textAlignment = NSTextAlignmentLeft;
161
+ // Single value - determine if it's horizontal or vertical
162
+ if ([alignment isEqualToString:@"top"] || [alignment isEqualToString:@"bottom"]) {
163
+ verticalPart = alignment;
164
+ } else {
165
+ horizontalPart = alignment;
166
+ }
167
+ }
168
+
169
+ // Apply horizontal alignment
170
+ if (horizontalPart) {
171
+ if ([horizontalPart isEqualToString:@"center"]) {
172
+ _textView.textAlignment = NSTextAlignmentCenter;
173
+ } else if ([horizontalPart isEqualToString:@"right"] || [horizontalPart isEqualToString:@"flex-end"]) {
174
+ _textView.textAlignment = NSTextAlignmentRight;
175
+ } else if ([horizontalPart isEqualToString:@"left"] || [horizontalPart isEqualToString:@"flex-start"]) {
176
+ _textView.textAlignment = NSTextAlignmentLeft;
177
+ } else if ([horizontalPart isEqualToString:@"justify"]) {
178
+ _textView.textAlignment = NSTextAlignmentJustified;
179
+ } else {
180
+ _textView.textAlignment = NSTextAlignmentLeft;
181
+ }
155
182
  }
183
+
184
+ // Apply vertical alignment via textContainerInset
185
+ if ([verticalPart isEqualToString:@"top"]) {
186
+ _textView.textContainerInset = UIEdgeInsetsMake(10, 10, 0, 10);
187
+ } else if ([verticalPart isEqualToString:@"bottom"]) {
188
+ // Calculate bottom alignment by adjusting top inset
189
+ CGFloat contentHeight = [_textView.layoutManager usedRectForTextContainer:_textView.textContainer].size.height;
190
+ CGFloat viewHeight = _textView.bounds.size.height;
191
+ CGFloat topInset = MAX(10, viewHeight - contentHeight - 10);
192
+ _textView.textContainerInset = UIEdgeInsetsMake(topInset, 10, 10, 10);
193
+ } else if (!verticalPart) {
194
+ // Default vertical centering for horizontal-only alignments
195
+ _textView.textContainerInset = UIEdgeInsetsMake(10, 10, 10, 10);
196
+ }
197
+
156
198
  [self applyCharacterBackgrounds]; // Reapply to update alignment
157
199
  }
158
200
 
@@ -220,6 +262,37 @@ using namespace facebook::react;
220
262
  _layoutManager.paddingBottom = _paddingBottom;
221
263
  }
222
264
  }
265
+
266
+ if (oldViewProps.text != newViewProps.text) {
267
+ NSString *text = [[NSString alloc] initWithUTF8String: newViewProps.text.c_str()];
268
+ if (![_textView.text isEqualToString:text]) {
269
+ _isUpdatingText = YES;
270
+ _textView.text = text;
271
+ [self applyCharacterBackgrounds];
272
+ _isUpdatingText = NO;
273
+ }
274
+ }
275
+
276
+ if (oldViewProps.isEditable != newViewProps.isEditable) {
277
+ _textView.editable = newViewProps.isEditable;
278
+ }
279
+
280
+ if (oldViewProps.verticalAlign != newViewProps.verticalAlign) {
281
+ NSString *verticalAlign = [[NSString alloc] initWithUTF8String: newViewProps.verticalAlign.c_str()];
282
+
283
+ if ([verticalAlign isEqualToString:@"top"]) {
284
+ _textView.textContainerInset = UIEdgeInsetsMake(10, 10, 0, 10);
285
+ } else if ([verticalAlign isEqualToString:@"bottom"]) {
286
+ CGFloat contentHeight = [_textView.layoutManager usedRectForTextContainer:_textView.textContainer].size.height;
287
+ CGFloat viewHeight = _textView.bounds.size.height;
288
+ CGFloat topInset = MAX(10, viewHeight - contentHeight - 10);
289
+ _textView.textContainerInset = UIEdgeInsetsMake(topInset, 10, 10, 10);
290
+ } else if ([verticalAlign isEqualToString:@"center"] || [verticalAlign isEqualToString:@"middle"]) {
291
+ _textView.textContainerInset = UIEdgeInsetsMake(10, 10, 10, 10);
292
+ }
293
+
294
+ [self applyCharacterBackgrounds];
295
+ }
223
296
 
224
297
  [super updateProps:props oldProps:oldProps];
225
298
  }
@@ -232,6 +305,14 @@ Class<RCTComponentViewProtocol> HighlightTextViewCls(void)
232
305
  - (void)textViewDidChange:(UITextView *)textView
233
306
  {
234
307
  [self applyCharacterBackgrounds];
308
+ if (!_isUpdatingText) {
309
+ if (_eventEmitter != nullptr) {
310
+ std::dynamic_pointer_cast<const HighlightTextViewEventEmitter>(_eventEmitter)
311
+ ->onChange(HighlightTextViewEventEmitter::OnChange{
312
+ .text = std::string([textView.text UTF8String] ?: "")
313
+ });
314
+ }
315
+ }
235
316
  }
236
317
 
237
318
  - (void)applyCharacterBackgrounds
@@ -1,9 +1,49 @@
1
- import { codegenNativeComponent, type ViewProps } from 'react-native';
1
+ import { codegenNativeComponent } from 'react-native';
2
+ import type { ViewProps } from 'react-native';
3
+ import type { BubblingEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
4
+
5
+ export interface OnChangeEventData {
6
+ readonly text: string;
7
+ }
8
+
9
+ /**
10
+ * Text alignment options
11
+ *
12
+ * Horizontal alignment:
13
+ * - 'left' or 'flex-start': Align text to the left
14
+ * - 'center': Center align text
15
+ * - 'right' or 'flex-end': Align text to the right
16
+ * - 'justify': Justify text (distribute evenly)
17
+ *
18
+ * Vertical alignment (iOS only):
19
+ * - 'top': Align to top
20
+ * - 'bottom': Align to bottom
21
+ *
22
+ * Combined alignment (iOS only):
23
+ * - 'top-left', 'top-center', 'top-right'
24
+ * - 'bottom-left', 'bottom-center', 'bottom-right'
25
+ */
26
+ export type TextAlignment =
27
+ | 'left'
28
+ | 'center'
29
+ | 'right'
30
+ | 'justify'
31
+ | 'flex-start'
32
+ | 'flex-end'
33
+ | 'top'
34
+ | 'bottom'
35
+ | 'top-left'
36
+ | 'top-center'
37
+ | 'top-right'
38
+ | 'bottom-left'
39
+ | 'bottom-center'
40
+ | 'bottom-right';
2
41
 
3
42
  export interface HighlightTextViewProps extends ViewProps {
4
43
  color?: string;
5
44
  textColor?: string;
6
45
  textAlign?: string;
46
+ verticalAlign?: string;
7
47
  fontFamily?: string;
8
48
  fontSize?: string;
9
49
  padding?: string;
@@ -11,6 +51,9 @@ export interface HighlightTextViewProps extends ViewProps {
11
51
  paddingRight?: string;
12
52
  paddingTop?: string;
13
53
  paddingBottom?: string;
54
+ text?: string;
55
+ isEditable?: boolean;
56
+ onChange?: BubblingEventHandler<OnChangeEventData>;
14
57
  }
15
58
 
16
59
  export default codegenNativeComponent<HighlightTextViewProps>(
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=codegen-types.d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["codegen-types.d.ts"],"mappings":"","ignoreList":[]}
@@ -1,8 +1,31 @@
1
- import { type ViewProps } from 'react-native';
1
+ import type { ViewProps } from 'react-native';
2
+ import type { BubblingEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
3
+ export interface OnChangeEventData {
4
+ readonly text: string;
5
+ }
6
+ /**
7
+ * Text alignment options
8
+ *
9
+ * Horizontal alignment:
10
+ * - 'left' or 'flex-start': Align text to the left
11
+ * - 'center': Center align text
12
+ * - 'right' or 'flex-end': Align text to the right
13
+ * - 'justify': Justify text (distribute evenly)
14
+ *
15
+ * Vertical alignment (iOS only):
16
+ * - 'top': Align to top
17
+ * - 'bottom': Align to bottom
18
+ *
19
+ * Combined alignment (iOS only):
20
+ * - 'top-left', 'top-center', 'top-right'
21
+ * - 'bottom-left', 'bottom-center', 'bottom-right'
22
+ */
23
+ export type TextAlignment = 'left' | 'center' | 'right' | 'justify' | 'flex-start' | 'flex-end' | 'top' | 'bottom' | 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
2
24
  export interface HighlightTextViewProps extends ViewProps {
3
25
  color?: string;
4
26
  textColor?: string;
5
27
  textAlign?: string;
28
+ verticalAlign?: string;
6
29
  fontFamily?: string;
7
30
  fontSize?: string;
8
31
  padding?: string;
@@ -10,6 +33,9 @@ export interface HighlightTextViewProps extends ViewProps {
10
33
  paddingRight?: string;
11
34
  paddingTop?: string;
12
35
  paddingBottom?: string;
36
+ text?: string;
37
+ isEditable?: boolean;
38
+ onChange?: BubblingEventHandler<OnChangeEventData>;
13
39
  }
14
40
  declare const _default: import("react-native/types_generated/Libraries/Utilities/codegenNativeComponent").NativeComponentType<HighlightTextViewProps>;
15
41
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"HighlightTextViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/HighlightTextViewNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAEtE,MAAM,WAAW,sBAAuB,SAAQ,SAAS;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,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;CACxB;;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,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,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.1",
3
+ "version": "0.1.3",
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",
@@ -1,9 +1,49 @@
1
- import { codegenNativeComponent, type ViewProps } from 'react-native';
1
+ import { codegenNativeComponent } from 'react-native';
2
+ import type { ViewProps } from 'react-native';
3
+ import type { BubblingEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
4
+
5
+ export interface OnChangeEventData {
6
+ readonly text: string;
7
+ }
8
+
9
+ /**
10
+ * Text alignment options
11
+ *
12
+ * Horizontal alignment:
13
+ * - 'left' or 'flex-start': Align text to the left
14
+ * - 'center': Center align text
15
+ * - 'right' or 'flex-end': Align text to the right
16
+ * - 'justify': Justify text (distribute evenly)
17
+ *
18
+ * Vertical alignment (iOS only):
19
+ * - 'top': Align to top
20
+ * - 'bottom': Align to bottom
21
+ *
22
+ * Combined alignment (iOS only):
23
+ * - 'top-left', 'top-center', 'top-right'
24
+ * - 'bottom-left', 'bottom-center', 'bottom-right'
25
+ */
26
+ export type TextAlignment =
27
+ | 'left'
28
+ | 'center'
29
+ | 'right'
30
+ | 'justify'
31
+ | 'flex-start'
32
+ | 'flex-end'
33
+ | 'top'
34
+ | 'bottom'
35
+ | 'top-left'
36
+ | 'top-center'
37
+ | 'top-right'
38
+ | 'bottom-left'
39
+ | 'bottom-center'
40
+ | 'bottom-right';
2
41
 
3
42
  export interface HighlightTextViewProps extends ViewProps {
4
43
  color?: string;
5
44
  textColor?: string;
6
45
  textAlign?: string;
46
+ verticalAlign?: string;
7
47
  fontFamily?: string;
8
48
  fontSize?: string;
9
49
  padding?: string;
@@ -11,6 +51,9 @@ export interface HighlightTextViewProps extends ViewProps {
11
51
  paddingRight?: string;
12
52
  paddingTop?: string;
13
53
  paddingBottom?: string;
54
+ text?: string;
55
+ isEditable?: boolean;
56
+ onChange?: BubblingEventHandler<OnChangeEventData>;
14
57
  }
15
58
 
16
59
  export default codegenNativeComponent<HighlightTextViewProps>(
@@ -0,0 +1,14 @@
1
+ declare module 'react-native/Libraries/Types/CodegenTypes' {
2
+ export type DirectEventHandler<T = {}> = (event: { nativeEvent: T }) => void;
3
+ export type BubblingEventHandler<T = {}> = (event: {
4
+ nativeEvent: T;
5
+ }) => void;
6
+ }
7
+
8
+ declare module 'react-native/Libraries/Utilities/codegenNativeComponent' {
9
+ import type { HostComponent } from 'react-native';
10
+ export default function codegenNativeComponent<T>(
11
+ componentName: string,
12
+ options?: {}
13
+ ): HostComponent<T>;
14
+ }