react-native-enriched 0.1.3 → 0.1.5
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 +36 -648
- package/ReactNativeEnriched.podspec +1 -1
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +32 -16
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewLayoutManager.kt +12 -2
- package/android/src/main/java/com/swmansion/enriched/events/MentionHandler.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +6 -2
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +9 -5
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +10 -5
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +11 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +11 -1
- package/android/src/main/java/com/swmansion/enriched/styles/ListStyles.kt +1 -2
- package/android/src/main/java/com/swmansion/enriched/styles/ParametrizedStyles.kt +12 -8
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSelection.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedTextWatcher.kt +2 -2
- package/android/src/main/new_arch/CMakeLists.txt +13 -9
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.h +2 -2
- package/ios/EnrichedTextInputView.mm +64 -56
- package/ios/internals/EnrichedTextInputViewShadowNode.mm +4 -1
- package/ios/styles/BlockQuoteStyle.mm +18 -23
- package/ios/styles/BoldStyle.mm +5 -2
- package/ios/styles/HeadingStyleBase.mm +37 -5
- package/ios/styles/InlineCodeStyle.mm +5 -2
- package/ios/styles/ItalicStyle.mm +5 -5
- package/ios/styles/OrderedListStyle.mm +18 -23
- package/ios/styles/StrikethroughStyle.mm +5 -2
- package/ios/styles/UnderlineStyle.mm +5 -2
- package/ios/styles/UnorderedListStyle.mm +18 -23
- package/ios/utils/OccurenceUtils.h +6 -0
- package/ios/utils/OccurenceUtils.mm +31 -0
- package/ios/utils/ParagraphAttributesUtils.h +6 -0
- package/ios/utils/ParagraphAttributesUtils.mm +67 -0
- package/ios/utils/StyleHeaders.h +2 -0
- package/ios/utils/ZeroWidthSpaceUtils.mm +14 -6
- package/package.json +6 -5
package/ios/styles/BoldStyle.mm
CHANGED
|
@@ -98,8 +98,11 @@
|
|
|
98
98
|
}
|
|
99
99
|
];
|
|
100
100
|
} else {
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
return [OccurenceUtils detect:NSFontAttributeName withInput:_input atIndex:range.location checkPrevious:NO
|
|
102
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
103
|
+
return [self styleCondition:value :range];
|
|
104
|
+
}
|
|
105
|
+
];
|
|
103
106
|
}
|
|
104
107
|
}
|
|
105
108
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#import "EnrichedTextInputView.h"
|
|
3
3
|
#import "FontExtension.h"
|
|
4
4
|
#import "OccurenceUtils.h"
|
|
5
|
+
#import "TextInsertionUtils.h"
|
|
5
6
|
|
|
6
7
|
@implementation HeadingStyleBase
|
|
7
8
|
|
|
@@ -116,11 +117,11 @@
|
|
|
116
117
|
}
|
|
117
118
|
];
|
|
118
119
|
} else {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
return [OccurenceUtils detect:NSFontAttributeName withInput:[self typedInput] atIndex:range.location checkPrevious:YES
|
|
121
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
122
|
+
return [self styleCondition:value :range];
|
|
123
|
+
}
|
|
124
|
+
];
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
|
|
@@ -140,5 +141,36 @@
|
|
|
140
141
|
];
|
|
141
142
|
}
|
|
142
143
|
|
|
144
|
+
// used to make sure headings dont persist after a newline is placed
|
|
145
|
+
- (BOOL)handleNewlinesInRange:(NSRange)range replacementText:(NSString *)text {
|
|
146
|
+
// in a heading and a new text ends with a newline
|
|
147
|
+
if(
|
|
148
|
+
[self detectStyle:[self typedInput]->textView.selectedRange] &&
|
|
149
|
+
text.length > 0 &&
|
|
150
|
+
[[NSCharacterSet newlineCharacterSet] characterIsMember: [text characterAtIndex:text.length-1]]
|
|
151
|
+
) {
|
|
152
|
+
// do the replacement manually
|
|
153
|
+
[TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:[self typedInput] withSelection:YES];
|
|
154
|
+
// remove the attribtues at the new selection
|
|
155
|
+
[self removeAttributes:[self typedInput]->textView.selectedRange];
|
|
156
|
+
return YES;
|
|
157
|
+
}
|
|
158
|
+
return NO;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// backspacing a line after a heading "into" a heading will not result in the text attaining heading attributes
|
|
162
|
+
// so, we do it manually
|
|
163
|
+
- (void)handleImproperHeadings {
|
|
164
|
+
NSArray *occurences = [self findAllOccurences:NSMakeRange(0, [self typedInput]->textView.textStorage.string.length)];
|
|
165
|
+
for(StylePair *pair in occurences) {
|
|
166
|
+
NSRange occurenceRange = [pair.rangeValue rangeValue];
|
|
167
|
+
NSRange paragraphRange = [[self typedInput]->textView.textStorage.string paragraphRangeForRange:occurenceRange];
|
|
168
|
+
if(!NSEqualRanges(occurenceRange, paragraphRange)) {
|
|
169
|
+
// we have a heading but it does not span its whole paragraph - let's fix it
|
|
170
|
+
[self addAttributes:paragraphRange];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
143
175
|
@end
|
|
144
176
|
|
|
@@ -140,8 +140,11 @@
|
|
|
140
140
|
|
|
141
141
|
return detected;
|
|
142
142
|
} else {
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
return [OccurenceUtils detect:NSBackgroundColorAttributeName withInput:_input atIndex:range.location checkPrevious:NO
|
|
144
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
145
|
+
return [self styleCondition:value :range];
|
|
146
|
+
}
|
|
147
|
+
];
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
150
|
|
|
@@ -83,11 +83,11 @@
|
|
|
83
83
|
}
|
|
84
84
|
];
|
|
85
85
|
} else {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
return [OccurenceUtils detect:NSFontAttributeName withInput:_input atIndex:range.location checkPrevious:NO
|
|
87
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
88
|
+
return [self styleCondition:value :range];
|
|
89
|
+
}
|
|
90
|
+
];
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
@@ -130,16 +130,22 @@
|
|
|
130
130
|
[self removeAttributes:_input->textView.selectedRange];
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
// removing first list point by backspacing doesn't remove typing attributes because it doesn't run textViewDidChange
|
|
134
|
-
// so we try guessing that a point should be deleted here
|
|
135
133
|
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text {
|
|
136
|
-
if([self detectStyle:_input->textView.selectedRange] &&
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
) {
|
|
134
|
+
if([self detectStyle:_input->textView.selectedRange] && text.length == 0) {
|
|
135
|
+
// backspace while the style is active
|
|
136
|
+
|
|
140
137
|
NSRange paragraphRange = [_input->textView.textStorage.string paragraphRangeForRange:_input->textView.selectedRange];
|
|
141
|
-
|
|
142
|
-
|
|
138
|
+
|
|
139
|
+
if(NSEqualRanges(_input->textView.selectedRange, NSMakeRange(0, 0))) {
|
|
140
|
+
// a backspace on the very first input's line list point
|
|
141
|
+
// it doesn't run textVieDidChange so we need to manually remove attributes
|
|
142
|
+
[self removeAttributes:paragraphRange];
|
|
143
|
+
return YES;
|
|
144
|
+
} else if(range.location == paragraphRange.location - 1) {
|
|
145
|
+
// same case in other lines; here, the removed range location will be exactly 1 less than paragraph range location
|
|
146
|
+
[self removeAttributes:paragraphRange];
|
|
147
|
+
return YES;
|
|
148
|
+
}
|
|
143
149
|
}
|
|
144
150
|
return NO;
|
|
145
151
|
}
|
|
@@ -187,22 +193,11 @@
|
|
|
187
193
|
}
|
|
188
194
|
];
|
|
189
195
|
} else {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
NSRange paragraphRange = NSMakeRange(0, 0);
|
|
197
|
-
NSRange inputRange = NSMakeRange(0, _input->textView.textStorage.length);
|
|
198
|
-
NSParagraphStyle *paragraph = [_input->textView.textStorage
|
|
199
|
-
attribute:NSParagraphStyleAttributeName
|
|
200
|
-
atIndex:searchLocation
|
|
201
|
-
longestEffectiveRange: ¶graphRange
|
|
202
|
-
inRange:inputRange
|
|
196
|
+
return [OccurenceUtils detect:NSParagraphStyleAttributeName withInput:_input atIndex:range.location checkPrevious:YES
|
|
197
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
198
|
+
return [self styleCondition:value :range];
|
|
199
|
+
}
|
|
203
200
|
];
|
|
204
|
-
|
|
205
|
-
return [self styleCondition:paragraph :NSMakeRange(0, 0)];
|
|
206
201
|
}
|
|
207
202
|
}
|
|
208
203
|
|
|
@@ -56,8 +56,11 @@
|
|
|
56
56
|
}
|
|
57
57
|
];
|
|
58
58
|
} else {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
return [OccurenceUtils detect:NSStrikethroughStyleAttributeName withInput:_input atIndex:range.location checkPrevious:NO
|
|
60
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
61
|
+
return [self styleCondition:value :range];
|
|
62
|
+
}
|
|
63
|
+
];
|
|
61
64
|
}
|
|
62
65
|
}
|
|
63
66
|
|
|
@@ -88,8 +88,11 @@
|
|
|
88
88
|
}
|
|
89
89
|
];
|
|
90
90
|
} else {
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
return [OccurenceUtils detect:NSUnderlineStyleAttributeName withInput:_input atIndex:range.location checkPrevious:NO
|
|
92
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
93
|
+
return [self styleCondition:value :range];
|
|
94
|
+
}
|
|
95
|
+
];
|
|
93
96
|
}
|
|
94
97
|
}
|
|
95
98
|
|
|
@@ -130,16 +130,22 @@
|
|
|
130
130
|
[self removeAttributes:_input->textView.selectedRange];
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
// removing first list point by backspacing doesn't remove typing attributes because it doesn't run textViewDidChange
|
|
134
|
-
// so we try guessing that a point should be deleted here
|
|
135
133
|
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text {
|
|
136
|
-
if([self detectStyle:_input->textView.selectedRange] &&
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
) {
|
|
134
|
+
if([self detectStyle:_input->textView.selectedRange] && text.length == 0) {
|
|
135
|
+
// backspace while the style is active
|
|
136
|
+
|
|
140
137
|
NSRange paragraphRange = [_input->textView.textStorage.string paragraphRangeForRange:_input->textView.selectedRange];
|
|
141
|
-
|
|
142
|
-
|
|
138
|
+
|
|
139
|
+
if(NSEqualRanges(_input->textView.selectedRange, NSMakeRange(0, 0))) {
|
|
140
|
+
// a backspace on the very first input's line list point
|
|
141
|
+
// it doesn't run textVieDidChange so we need to manually remove attributes
|
|
142
|
+
[self removeAttributes:paragraphRange];
|
|
143
|
+
return YES;
|
|
144
|
+
} else if(range.location == paragraphRange.location - 1) {
|
|
145
|
+
// same case in other lines; here, the removed range location will be exactly 1 less than paragraph range location
|
|
146
|
+
[self removeAttributes:paragraphRange];
|
|
147
|
+
return YES;
|
|
148
|
+
}
|
|
143
149
|
}
|
|
144
150
|
return NO;
|
|
145
151
|
}
|
|
@@ -187,22 +193,11 @@
|
|
|
187
193
|
}
|
|
188
194
|
];
|
|
189
195
|
} else {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
NSRange paragraphRange = NSMakeRange(0, 0);
|
|
197
|
-
NSRange inputRange = NSMakeRange(0, _input->textView.textStorage.length);
|
|
198
|
-
NSParagraphStyle *paragraph = [_input->textView.textStorage
|
|
199
|
-
attribute:NSParagraphStyleAttributeName
|
|
200
|
-
atIndex:searchLocation
|
|
201
|
-
longestEffectiveRange: ¶graphRange
|
|
202
|
-
inRange:inputRange
|
|
196
|
+
return [OccurenceUtils detect:NSParagraphStyleAttributeName withInput:_input atIndex:range.location checkPrevious:YES
|
|
197
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
198
|
+
return [self styleCondition:value :range];
|
|
199
|
+
}
|
|
203
200
|
];
|
|
204
|
-
|
|
205
|
-
return [self styleCondition:paragraph :NSMakeRange(0, 0)];
|
|
206
201
|
}
|
|
207
202
|
}
|
|
208
203
|
|
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
withInput:(EnrichedTextInputView* _Nonnull)input
|
|
10
10
|
inRange:(NSRange)range
|
|
11
11
|
withCondition:(BOOL (NS_NOESCAPE ^_Nonnull)(id _Nullable value, NSRange range))condition;
|
|
12
|
+
+ (BOOL)detect
|
|
13
|
+
:(NSAttributedStringKey _Nonnull)key
|
|
14
|
+
withInput:(EnrichedTextInputView* _Nonnull)input
|
|
15
|
+
atIndex:(NSUInteger)index
|
|
16
|
+
checkPrevious:(BOOL)check
|
|
17
|
+
withCondition:(BOOL (NS_NOESCAPE ^_Nonnull)(id _Nullable value, NSRange range))condition;
|
|
12
18
|
+ (BOOL)detectMultiple
|
|
13
19
|
:(NSArray<NSAttributedStringKey> *_Nonnull)keys
|
|
14
20
|
withInput:(EnrichedTextInputView* _Nonnull)input
|
|
@@ -19,6 +19,37 @@
|
|
|
19
19
|
return totalLength == range.length;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// checkPrevious flag is used for styles like lists or blockquotes
|
|
23
|
+
// it means that first character of paragraph will be checked instead if the detection is not in input's selected range and at the end of the input
|
|
24
|
+
+ (BOOL)detect
|
|
25
|
+
:(NSAttributedStringKey _Nonnull)key
|
|
26
|
+
withInput:(EnrichedTextInputView* _Nonnull)input
|
|
27
|
+
atIndex:(NSUInteger)index
|
|
28
|
+
checkPrevious:(BOOL)checkPrev
|
|
29
|
+
withCondition:(BOOL (NS_NOESCAPE ^_Nonnull)(id _Nullable value, NSRange range))condition
|
|
30
|
+
{
|
|
31
|
+
NSRange detectionRange = NSMakeRange(index, 0);
|
|
32
|
+
id attrValue;
|
|
33
|
+
if(NSEqualRanges(input->textView.selectedRange, detectionRange)) {
|
|
34
|
+
attrValue = input->textView.typingAttributes[key];
|
|
35
|
+
} else if(index == input->textView.textStorage.string.length) {
|
|
36
|
+
if(checkPrev) {
|
|
37
|
+
NSRange paragraphRange = [input->textView.textStorage.string paragraphRangeForRange:detectionRange];
|
|
38
|
+
if(paragraphRange.location == detectionRange.location) {
|
|
39
|
+
return NO;
|
|
40
|
+
} else {
|
|
41
|
+
return [self detect:key withInput:input inRange:NSMakeRange(paragraphRange.location, 1) withCondition:condition];
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
return NO;
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
NSRange attrRange = NSMakeRange(0, 0);
|
|
48
|
+
attrValue = [input->textView.textStorage attribute:key atIndex:index effectiveRange:&attrRange];
|
|
49
|
+
}
|
|
50
|
+
return condition(attrValue, detectionRange);
|
|
51
|
+
}
|
|
52
|
+
|
|
22
53
|
+ (BOOL)detectMultiple
|
|
23
54
|
:(NSArray<NSAttributedStringKey> *_Nonnull)keys
|
|
24
55
|
withInput:(EnrichedTextInputView* _Nonnull)input
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#import "ParagraphAttributesUtils.h"
|
|
2
|
+
#import "EnrichedTextInputView.h"
|
|
3
|
+
#import "StyleHeaders.h"
|
|
4
|
+
#import "ParagraphsUtils.h"
|
|
5
|
+
#import "TextInsertionUtils.h"
|
|
6
|
+
|
|
7
|
+
@implementation ParagraphAttributesUtils
|
|
8
|
+
|
|
9
|
+
// if the user backspaces the last character in a line, the iOS applies typing attributes from the previous line
|
|
10
|
+
// in the case of some paragraph styles it works especially bad when a list point just appears
|
|
11
|
+
// hence the solution - reset typing attributes
|
|
12
|
+
+ (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text input:(id)input {
|
|
13
|
+
EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
|
|
14
|
+
UnorderedListStyle *ulStyle = typedInput->stylesDict[@([UnorderedListStyle getStyleType])];
|
|
15
|
+
OrderedListStyle *olStyle = typedInput->stylesDict[@([OrderedListStyle getStyleType])];
|
|
16
|
+
BlockQuoteStyle *bqStyle = typedInput->stylesDict[@([BlockQuoteStyle getStyleType])];
|
|
17
|
+
|
|
18
|
+
if(typedInput == nullptr) {
|
|
19
|
+
return NO;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// we make sure it was a backspace (text with 0 length) and it deleted something (range longer than 0)
|
|
23
|
+
if(text.length > 0 || range.length == 0) {
|
|
24
|
+
return NO;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// find a non-newline range of the paragraph
|
|
28
|
+
NSRange paragraphRange = [typedInput->textView.textStorage.string paragraphRangeForRange:range];
|
|
29
|
+
|
|
30
|
+
NSArray *paragraphs = [ParagraphsUtils getNonNewlineRangesIn:typedInput->textView range:paragraphRange];
|
|
31
|
+
if(paragraphs.count == 0) {
|
|
32
|
+
return NO;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
NSRange nonNewlineRange = [(NSValue *)paragraphs.firstObject rangeValue];
|
|
36
|
+
|
|
37
|
+
// if the backspace removes the whole content of a paragraph (possibly more but has to start where the paragraph starts), we remove the typing attributes
|
|
38
|
+
if(range.location == nonNewlineRange.location && range.length >= nonNewlineRange.length) {
|
|
39
|
+
// for lists and quotes we want to remove the characters but keep attribtues so that a zero width space appears here
|
|
40
|
+
// so we do the removing manually and reapply attributes
|
|
41
|
+
if([ulStyle detectStyle:nonNewlineRange]) {
|
|
42
|
+
[TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:typedInput withSelection:YES];
|
|
43
|
+
[ulStyle addAttributes:NSMakeRange(range.location, 0)];
|
|
44
|
+
return YES;
|
|
45
|
+
}
|
|
46
|
+
if([olStyle detectStyle:nonNewlineRange]) {
|
|
47
|
+
[TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:typedInput withSelection:YES];
|
|
48
|
+
[olStyle addAttributes:NSMakeRange(range.location, 0)];
|
|
49
|
+
return YES;
|
|
50
|
+
}
|
|
51
|
+
if([bqStyle detectStyle:nonNewlineRange]) {
|
|
52
|
+
[TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:typedInput withSelection:YES];
|
|
53
|
+
[bqStyle addAttributes:NSMakeRange(range.location, 0)];
|
|
54
|
+
return YES;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// do the replacement manually
|
|
58
|
+
[TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:typedInput withSelection:YES];
|
|
59
|
+
// reset typing attribtues
|
|
60
|
+
typedInput->textView.typingAttributes = typedInput->defaultTypingAttributes;
|
|
61
|
+
return YES;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return NO;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@end
|
package/ios/utils/StyleHeaders.h
CHANGED
|
@@ -52,19 +52,23 @@
|
|
|
52
52
|
|
|
53
53
|
// do the removing
|
|
54
54
|
NSInteger offset = 0;
|
|
55
|
-
NSInteger
|
|
55
|
+
NSInteger postRemoveLocationOffset = 0;
|
|
56
|
+
NSInteger postRemoveLengthOffset = 0;
|
|
56
57
|
for(NSNumber *index in indexesToBeRemoved) {
|
|
57
58
|
NSRange replaceRange = NSMakeRange([index integerValue] + offset, 1);
|
|
58
59
|
[TextInsertionUtils replaceText:@"" at:replaceRange additionalAttributes:nullptr input:input withSelection:NO];
|
|
59
60
|
offset -= 1;
|
|
60
61
|
if([index integerValue] < preRemoveSelection.location) {
|
|
61
|
-
|
|
62
|
+
postRemoveLocationOffset -= 1;
|
|
63
|
+
}
|
|
64
|
+
if([index integerValue] >= preRemoveSelection.location && [index integerValue] < NSMaxRange(preRemoveSelection)) {
|
|
65
|
+
postRemoveLengthOffset -= 1;
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
// fix the selection if needed
|
|
66
70
|
if([input->textView isFirstResponder]) {
|
|
67
|
-
input->textView.selectedRange = NSMakeRange(preRemoveSelection.location +
|
|
71
|
+
input->textView.selectedRange = NSMakeRange(preRemoveSelection.location + postRemoveLocationOffset, preRemoveSelection.length + postRemoveLengthOffset);
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
|
|
@@ -93,13 +97,17 @@
|
|
|
93
97
|
|
|
94
98
|
// do the replacing
|
|
95
99
|
NSInteger offset = 0;
|
|
96
|
-
NSInteger
|
|
100
|
+
NSInteger postAddLocationOffset = 0;
|
|
101
|
+
NSInteger postAddLengthOffset = 0;
|
|
97
102
|
for(NSNumber *index in indexesToBeInserted) {
|
|
98
103
|
NSRange replaceRange = NSMakeRange([index integerValue] + offset, 1);
|
|
99
104
|
[TextInsertionUtils replaceText:@"\u200B\n" at:replaceRange additionalAttributes:nullptr input:input withSelection:NO];
|
|
100
105
|
offset += 1;
|
|
101
106
|
if([index integerValue] < preAddSelection.location) {
|
|
102
|
-
|
|
107
|
+
postAddLocationOffset += 1;
|
|
108
|
+
}
|
|
109
|
+
if([index integerValue] >= preAddSelection.location && [index integerValue] < NSMaxRange(preAddSelection)) {
|
|
110
|
+
postAddLengthOffset += 1;
|
|
103
111
|
}
|
|
104
112
|
}
|
|
105
113
|
|
|
@@ -112,7 +120,7 @@
|
|
|
112
120
|
|
|
113
121
|
// fix the selection if needed
|
|
114
122
|
if([input->textView isFirstResponder]) {
|
|
115
|
-
input->textView.selectedRange = NSMakeRange(preAddSelection.location +
|
|
123
|
+
input->textView.selectedRange = NSMakeRange(preAddSelection.location + postAddLocationOffset, preAddSelection.length + postAddLengthOffset);
|
|
116
124
|
}
|
|
117
125
|
}
|
|
118
126
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-enriched",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Rich Text Editor component for React Native",
|
|
5
5
|
"source": "./src/index.tsx",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
40
40
|
"prepare": "bob build",
|
|
41
41
|
"release": "release-it",
|
|
42
|
-
"android-studio": "open -a 'Android Studio' example/android"
|
|
42
|
+
"android-studio": "open -a 'Android Studio' example/android",
|
|
43
|
+
"xcode": "open -a 'Xcode' example/ios/EnrichedTextInputExample.xcworkspace"
|
|
43
44
|
},
|
|
44
45
|
"keywords": [
|
|
45
46
|
"react-native",
|
|
@@ -48,14 +49,14 @@
|
|
|
48
49
|
],
|
|
49
50
|
"repository": {
|
|
50
51
|
"type": "git",
|
|
51
|
-
"url": "git+https://github.com/software-mansion
|
|
52
|
+
"url": "git+https://github.com/software-mansion/react-native-enriched.git"
|
|
52
53
|
},
|
|
53
54
|
"author": "Software Mansion <contact@swmansion.com> (https://swmansion.com)",
|
|
54
55
|
"license": "MIT",
|
|
55
56
|
"bugs": {
|
|
56
|
-
"url": "https://github.com/software-mansion
|
|
57
|
+
"url": "https://github.com/software-mansion/react-native-enriched/issues"
|
|
57
58
|
},
|
|
58
|
-
"homepage": "https://github.com/software-mansion
|
|
59
|
+
"homepage": "https://github.com/software-mansion/react-native-enriched#readme",
|
|
59
60
|
"publishConfig": {
|
|
60
61
|
"registry": "https://registry.npmjs.org/"
|
|
61
62
|
},
|