react-native-typerich 2.2.2 → 2.2.4

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
@@ -1,7 +1,6 @@
1
1
  # react-native-typerich
2
2
 
3
3
  Drop in TextInput replacement with inbuilt support for Image Pasting and Gboard stickers
4
- currently available only for android
5
4
 
6
5
  ## Installation
7
6
 
@@ -60,82 +60,77 @@
60
60
  /// setText(text) - diff-based with proper cursor tracking, non-undoable
61
61
  - (void)setText:(NSString *)text
62
62
  {
63
- UITextView *tv = _textView;
64
- TypeRichTextInputView *owner = _owner;
65
- if (!tv || !owner) return;
66
-
67
- dispatch_async(dispatch_get_main_queue(), ^{
68
- // Never interrupt IME composition
69
- if (tv.markedTextRange) return;
70
-
71
- NSString *newText = text ?: @"";
72
- NSString *currentText = tv.text ?: @"";
73
-
74
- // commented for now as causing issues when textinput is blank
75
- // if ([currentText isEqualToString:newText]) {
76
- // return;
77
- // }
78
-
79
- owner.blockEmitting = YES;
80
-
81
- NSRange oldSelection = tv.selectedRange;
82
-
83
- // Calculate minimal diff range
84
- NSRange diffRange = [self calculateDiffRange:currentText newText:newText];
85
-
86
- // Calculate what text will be inserted
87
- NSInteger newLength = newText.length - (currentText.length - diffRange.length);
88
- NSString *replacementText = @"";
89
-
90
- if (newLength > 0) {
91
- replacementText = [newText substringWithRange:NSMakeRange(diffRange.location, newLength)];
92
- }
93
-
94
- // Convert NSRange to UITextRange
95
- UITextPosition *start = [tv positionFromPosition:tv.beginningOfDocument
96
- offset:diffRange.location];
97
- UITextPosition *end = [tv positionFromPosition:tv.beginningOfDocument
98
- offset:NSMaxRange(diffRange)];
99
-
100
- if (start && end) {
101
- UITextRange *range = [tv textRangeFromPosition:start toPosition:end];
102
- [tv replaceRange:range withText:replacementText];
103
-
104
- // Calculate cursor adjustment
105
- NSInteger delta = replacementText.length - diffRange.length;
106
- NSInteger newCursorPos = oldSelection.location;
107
-
108
- // If change happened before cursor, adjust cursor position
109
- if (diffRange.location <= oldSelection.location) {
110
- newCursorPos = oldSelection.location + delta;
111
- }
112
-
113
- // Clamp to valid range
114
- newCursorPos = MAX(0, MIN(newCursorPos, newText.length));
115
-
116
- // Restore cursor at adjusted position
117
- tv.selectedRange = NSMakeRange(newCursorPos, 0);
118
-
119
- } else {
120
- // Fallback: full replace with cursor clamping
121
- tv.text = newText;
122
- NSInteger safeLoc = MIN(oldSelection.location, newText.length);
123
- tv.selectedRange = NSMakeRange(safeLoc, 0);
124
- }
125
-
126
- owner.blockEmitting = NO;
127
-
128
- [owner updatePlaceholderVisibilityFromCommand];
129
-
130
- if (tv.scrollEnabled) {
131
- [owner invalidateTextLayoutFromCommand];
132
-
133
- // scroll to cursor
134
- [tv scrollRangeToVisible:tv.selectedRange];
135
- }
136
-
137
- [owner dispatchSelectionChangeIfNeeded];
138
- });
63
+ UITextView *tv = _textView;
64
+ TypeRichTextInputView *owner = _owner;
65
+ if (!tv || !owner) return;
66
+
67
+ dispatch_async(dispatch_get_main_queue(), ^{
68
+ if (tv.markedTextRange) return;
69
+
70
+ NSString *newText = text ?: @"";
71
+ NSString *currentText = tv.text ?: @"";
72
+
73
+ // if text is same, do nothing.
74
+ if ([currentText isEqualToString:newText]) {
75
+ return;
76
+ }
77
+
78
+ owner.blockEmitting = YES;
79
+
80
+ NSRange oldSelection = tv.selectedRange;
81
+ NSRange diffRange = [self calculateDiffRange:currentText newText:newText];
82
+
83
+ NSInteger newLength = newText.length - (currentText.length - diffRange.length);
84
+ NSString *replacementText = (newLength > 0)
85
+ ? [newText substringWithRange:NSMakeRange(diffRange.location, newLength)]
86
+ : @"";
87
+
88
+ UITextPosition *start = [tv positionFromPosition:tv.beginningOfDocument offset:diffRange.location];
89
+ UITextPosition *end = [tv positionFromPosition:tv.beginningOfDocument offset:NSMaxRange(diffRange)];
90
+
91
+ if (start && end) {
92
+ UITextRange *range = [tv textRangeFromPosition:start toPosition:end];
93
+
94
+ // text replacement
95
+ [tv replaceRange:range withText:replacementText];
96
+
97
+ // if the user is typing at the end of the selection,
98
+ // and we just inserted text that matches what the system expected,
99
+ // we should only jump the cursor if the JS-provided state differs
100
+ // from the current internal state.
101
+
102
+ NSInteger delta = replacementText.length - diffRange.length;
103
+ BOOL cursorWasAtEnd = (oldSelection.location == currentText.length);
104
+
105
+ if (cursorWasAtEnd) {
106
+ tv.selectedRange = NSMakeRange(newText.length, 0);
107
+ } else {
108
+ // If the change happened at or before the cursor, shift it
109
+ if (diffRange.location <= oldSelection.location) {
110
+ NSInteger newPos = oldSelection.location + delta;
111
+ newPos = MAX(0, MIN(newPos, newText.length));
112
+
113
+ // IMPORTANT: Only set the range if it's actually different.
114
+ // Setting selectedRange unnecessarily resets the keyboard's internal state.
115
+ if (tv.selectedRange.location != newPos) {
116
+ tv.selectedRange = NSMakeRange(newPos, 0);
117
+ }
118
+ }
119
+ }
120
+ } else {
121
+ tv.text = newText;
122
+ }
123
+
124
+ owner.blockEmitting = NO;
125
+ [owner updatePlaceholderVisibilityFromCommand];
126
+
127
+ if (tv.scrollEnabled) {
128
+ [owner invalidateTextLayoutFromCommand];
129
+ [tv scrollRangeToVisible:tv.selectedRange];
130
+ }
131
+
132
+ [owner dispatchSelectionChangeIfNeeded];
133
+ });
139
134
  }
140
135
 
141
136
  // Helper: Calculate minimal diff range between two strings
@@ -24,6 +24,7 @@ const TypeRichTextInput = /*#__PURE__*/forwardRef((props, ref) => {
24
24
  const nativeRef = useRef(null);
25
25
  const {
26
26
  scrollEnabled = true,
27
+ editable = true,
27
28
  ...restProps
28
29
  } = props;
29
30
  useImperativeHandle(ref, () => ({
@@ -81,6 +82,7 @@ const TypeRichTextInput = /*#__PURE__*/forwardRef((props, ref) => {
81
82
  ref: nativeRef,
82
83
  ...restProps,
83
84
  scrollEnabled: scrollEnabled,
85
+ editable: editable,
84
86
  onInputFocus: () => props.onFocus?.(),
85
87
  onInputBlur: () => props.onBlur?.(),
86
88
  onChangeText: handleOnChangeTextEvent,
@@ -1 +1 @@
1
- {"version":3,"names":["forwardRef","useImperativeHandle","useRef","NativeTypeRichTextInput","Commands","jsx","_jsx","normalizeEvent","event","nativeEvent","TypeRichTextInput","props","ref","nativeRef","scrollEnabled","restProps","focus","current","blur","setText","text","setSelection","start","end","insertTextAt","getNativeRef","handlePasteImage","data","undefined","onPasteImageData","handleOnChangeTextEvent","e","onChangeText","value","handleonChangeSelectionEvent","onChangeSelection","onInputFocus","onFocus","onInputBlur","onBlur","onPasteImage"],"sourceRoot":"../../src","sources":["TypeRichTextInput.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["forwardRef","useImperativeHandle","useRef","NativeTypeRichTextInput","Commands","jsx","_jsx","normalizeEvent","event","nativeEvent","TypeRichTextInput","props","ref","nativeRef","scrollEnabled","editable","restProps","focus","current","blur","setText","text","setSelection","start","end","insertTextAt","getNativeRef","handlePasteImage","data","undefined","onPasteImageData","handleOnChangeTextEvent","e","onChangeText","value","handleonChangeSelectionEvent","onChangeSelection","onInputFocus","onFocus","onInputBlur","onBlur","onPasteImage"],"sourceRoot":"../../src","sources":["TypeRichTextInput.tsx"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"TypeRichTextInput.d.ts","sourceRoot":"","sources":["../../../src/TypeRichTextInput.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAEnC,KAAK,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,WAAW,EAAE,CAAC,CAAA;CAAE,CAAC;AAElD,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAK/D;AAED;;;;;;;;;GASG;AACH,QAAA,MAAM,iBAAiB,yHAuFtB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"TypeRichTextInput.d.ts","sourceRoot":"","sources":["../../../src/TypeRichTextInput.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAEnC,KAAK,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,WAAW,EAAE,CAAC,CAAA;CAAE,CAAC;AAElD,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAK/D;AAED;;;;;;;;;GASG;AACH,QAAA,MAAM,iBAAiB,yHAwFtB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-typerich",
3
- "version": "2.2.2",
3
+ "version": "2.2.4",
4
4
  "description": "Drop in TextInput replacement with inbuilt support for Image Pasting and Gboard stickers",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -39,7 +39,7 @@ const TypeRichTextInput = forwardRef(
39
39
  (props: TypeRichTextInputProps, ref: Ref<TypeRichTextInputRef>) => {
40
40
  const nativeRef = useRef(null);
41
41
 
42
- const { scrollEnabled = true, ...restProps } = props;
42
+ const { scrollEnabled = true, editable = true, ...restProps } = props;
43
43
 
44
44
  useImperativeHandle(ref, () => ({
45
45
  focus: () => {
@@ -114,6 +114,7 @@ const TypeRichTextInput = forwardRef(
114
114
  ref={nativeRef}
115
115
  {...restProps}
116
116
  scrollEnabled={scrollEnabled}
117
+ editable={editable}
117
118
  onInputFocus={() => props.onFocus?.()}
118
119
  onInputBlur={() => props.onBlur?.()}
119
120
  onChangeText={handleOnChangeTextEvent}