react-native-enriched 0.4.0 → 0.5.0
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 +27 -2
- package/ReactNativeEnriched.podspec +5 -1
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +12 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +4 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.cpp +149 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.h +146 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.cpp +16 -1
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.h +46 -0
- package/android/src/main/java/com/swmansion/enriched/common/GumboNormalizer.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCheckboxListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnorderedListSpan.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputView.kt +166 -20
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewManager.kt +32 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/MeasurementStore.kt +19 -2
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnContextMenuItemPressEvent.kt +35 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedLineHeightSpan.kt +44 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParagraphStyles.kt +19 -14
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParametrizedStyles.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpanState.kt +18 -12
- package/android/src/main/new_arch/CMakeLists.txt +9 -13
- package/android/src/main/new_arch/GumboNormalizerJni.cpp +14 -0
- package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/conversions.h +2 -21
- package/cpp/CMakeLists.txt +50 -0
- package/cpp/GumboParser/GumboParser.h +34043 -0
- package/cpp/README.md +59 -0
- package/cpp/parser/GumboNormalizer.c +915 -0
- package/cpp/parser/GumboParser.cpp +16 -0
- package/cpp/parser/GumboParser.hpp +23 -0
- package/cpp/tests/GumboParserTest.cpp +457 -0
- package/ios/EnrichedTextInputView.h +2 -0
- package/ios/EnrichedTextInputView.mm +160 -2
- package/ios/config/InputConfig.h +3 -0
- package/ios/config/InputConfig.mm +15 -0
- package/ios/extensions/LayoutManagerExtension.mm +34 -11
- package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.cpp +149 -0
- package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.h +146 -0
- package/ios/generated/ReactNativeEnrichedSpec/Props.cpp +16 -1
- package/ios/generated/ReactNativeEnrichedSpec/Props.h +46 -0
- package/ios/generated/ReactNativeEnrichedSpec/RCTComponentViewHelpers.h +29 -0
- package/ios/inputParser/InputParser.mm +27 -0
- package/ios/interfaces/ImageAttachment.mm +29 -0
- package/lib/module/EnrichedTextInput.js +43 -30
- package/lib/module/EnrichedTextInput.js.map +1 -1
- package/lib/module/spec/EnrichedTextInputNativeComponent.ts +118 -22
- package/lib/typescript/src/EnrichedTextInput.d.ts +24 -6
- package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts +111 -21
- package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/EnrichedTextInput.tsx +79 -40
- package/src/index.tsx +0 -1
- package/src/spec/EnrichedTextInputNativeComponent.ts +118 -22
|
@@ -50,6 +50,7 @@ using namespace facebook::react;
|
|
|
50
50
|
BOOL _emitFocusBlur;
|
|
51
51
|
BOOL _emitTextChange;
|
|
52
52
|
NSMutableDictionary<NSValue *, UIImageView *> *_attachmentViews;
|
|
53
|
+
NSArray<NSDictionary *> *_contextMenuItems;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
// MARK: - Component utils
|
|
@@ -332,6 +333,11 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
332
333
|
stylePropChanged = YES;
|
|
333
334
|
}
|
|
334
335
|
|
|
336
|
+
if (newViewProps.lineHeight != oldViewProps.lineHeight) {
|
|
337
|
+
[newConfig setPrimaryLineHeight:newViewProps.lineHeight];
|
|
338
|
+
stylePropChanged = YES;
|
|
339
|
+
}
|
|
340
|
+
|
|
335
341
|
if (newViewProps.fontWeight != oldViewProps.fontWeight) {
|
|
336
342
|
if (!newViewProps.fontWeight.empty()) {
|
|
337
343
|
[newConfig
|
|
@@ -731,11 +737,16 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
731
737
|
[config primaryColor];
|
|
732
738
|
defaultTypingAttributes[NSStrikethroughColorAttributeName] =
|
|
733
739
|
[config primaryColor];
|
|
734
|
-
|
|
735
|
-
[[
|
|
740
|
+
NSMutableParagraphStyle *defaultPStyle =
|
|
741
|
+
[[NSMutableParagraphStyle alloc] init];
|
|
742
|
+
defaultPStyle.minimumLineHeight = [config scaledPrimaryLineHeight];
|
|
743
|
+
defaultTypingAttributes[NSParagraphStyleAttributeName] = defaultPStyle;
|
|
744
|
+
|
|
736
745
|
textView.typingAttributes = defaultTypingAttributes;
|
|
737
746
|
textView.selectedRange = prevSelectedRange;
|
|
738
747
|
|
|
748
|
+
// make sure the newest lineHeight is applied
|
|
749
|
+
[self refreshLineHeight];
|
|
739
750
|
// update the placeholder as well
|
|
740
751
|
[self refreshPlaceholderLabelStyles];
|
|
741
752
|
}
|
|
@@ -745,6 +756,11 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
745
756
|
textView.editable = newViewProps.editable;
|
|
746
757
|
}
|
|
747
758
|
|
|
759
|
+
// useHtmlNormalizer
|
|
760
|
+
if (newViewProps.useHtmlNormalizer != oldViewProps.useHtmlNormalizer) {
|
|
761
|
+
useHtmlNormalizer = newViewProps.useHtmlNormalizer;
|
|
762
|
+
}
|
|
763
|
+
|
|
748
764
|
// default value - must be set before placeholder to make sure it correctly
|
|
749
765
|
// shows on first mount
|
|
750
766
|
if (newViewProps.defaultValue != oldViewProps.defaultValue) {
|
|
@@ -850,6 +866,26 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
850
866
|
// isOnChangeTextSet
|
|
851
867
|
_emitTextChange = newViewProps.isOnChangeTextSet;
|
|
852
868
|
|
|
869
|
+
// contextMenuItems
|
|
870
|
+
bool contextMenuChanged = newViewProps.contextMenuItems.size() !=
|
|
871
|
+
oldViewProps.contextMenuItems.size();
|
|
872
|
+
if (!contextMenuChanged) {
|
|
873
|
+
for (size_t i = 0; i < newViewProps.contextMenuItems.size(); i++) {
|
|
874
|
+
if (newViewProps.contextMenuItems[i].text !=
|
|
875
|
+
oldViewProps.contextMenuItems[i].text) {
|
|
876
|
+
contextMenuChanged = true;
|
|
877
|
+
break;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
if (contextMenuChanged) {
|
|
882
|
+
NSMutableArray<NSString *> *items = [NSMutableArray new];
|
|
883
|
+
for (const auto &item : newViewProps.contextMenuItems) {
|
|
884
|
+
[items addObject:[NSString fromCppString:item.text]];
|
|
885
|
+
}
|
|
886
|
+
_contextMenuItems = [items copy];
|
|
887
|
+
}
|
|
888
|
+
|
|
853
889
|
[super updateProps:props oldProps:oldProps];
|
|
854
890
|
// run the changes callback
|
|
855
891
|
[self anyTextMayHaveBeenModified];
|
|
@@ -880,6 +916,24 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
880
916
|
_placeholderLabel.attributedText = newAttrStr;
|
|
881
917
|
}
|
|
882
918
|
|
|
919
|
+
- (void)refreshLineHeight {
|
|
920
|
+
[textView.textStorage
|
|
921
|
+
enumerateAttribute:NSParagraphStyleAttributeName
|
|
922
|
+
inRange:NSMakeRange(0, textView.textStorage.string.length)
|
|
923
|
+
options:0
|
|
924
|
+
usingBlock:^(id _Nullable value, NSRange range,
|
|
925
|
+
BOOL *_Nonnull stop) {
|
|
926
|
+
NSMutableParagraphStyle *pStyle =
|
|
927
|
+
[(NSParagraphStyle *)value mutableCopy];
|
|
928
|
+
if (pStyle == nil)
|
|
929
|
+
return;
|
|
930
|
+
pStyle.minimumLineHeight = [config scaledPrimaryLineHeight];
|
|
931
|
+
[textView.textStorage addAttribute:NSParagraphStyleAttributeName
|
|
932
|
+
value:pStyle
|
|
933
|
+
range:range];
|
|
934
|
+
}];
|
|
935
|
+
}
|
|
936
|
+
|
|
883
937
|
// MARK: - Measuring and states
|
|
884
938
|
|
|
885
939
|
- (CGSize)measureSize:(CGFloat)maxWidth {
|
|
@@ -1180,6 +1234,10 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1180
1234
|
NSString *text = (NSString *)args[2];
|
|
1181
1235
|
NSString *url = (NSString *)args[3];
|
|
1182
1236
|
[self addLinkAt:start end:end text:text url:url];
|
|
1237
|
+
} else if ([commandName isEqualToString:@"removeLink"]) {
|
|
1238
|
+
NSInteger start = [((NSNumber *)args[0]) integerValue];
|
|
1239
|
+
NSInteger end = [((NSNumber *)args[1]) integerValue];
|
|
1240
|
+
[self removeLinkAt:start end:end];
|
|
1183
1241
|
} else if ([commandName isEqualToString:@"addMention"]) {
|
|
1184
1242
|
NSString *indicator = (NSString *)args[0];
|
|
1185
1243
|
NSString *text = (NSString *)args[1];
|
|
@@ -1468,6 +1526,29 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1468
1526
|
}
|
|
1469
1527
|
}
|
|
1470
1528
|
|
|
1529
|
+
- (void)removeLinkAt:(NSInteger)start end:(NSInteger)end {
|
|
1530
|
+
LinkStyle *linkStyleClass =
|
|
1531
|
+
(LinkStyle *)stylesDict[@([LinkStyle getStyleType])];
|
|
1532
|
+
if (linkStyleClass == nullptr) {
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
NSInteger textLength = (NSInteger)textView.textStorage.length;
|
|
1537
|
+
if (start < 0) {
|
|
1538
|
+
start = 0;
|
|
1539
|
+
}
|
|
1540
|
+
if (end > textLength) {
|
|
1541
|
+
end = textLength;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
NSInteger rangeStart = MIN(start, end);
|
|
1545
|
+
NSInteger rangeLength = MAX(start, end) - rangeStart;
|
|
1546
|
+
NSRange linkRange = NSMakeRange(rangeStart, rangeLength);
|
|
1547
|
+
|
|
1548
|
+
[linkStyleClass removeAttributes:linkRange];
|
|
1549
|
+
[self anyTextMayHaveBeenModified];
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1471
1552
|
- (void)addMention:(NSString *)indicator
|
|
1472
1553
|
text:(NSString *)text
|
|
1473
1554
|
attributes:(NSString *)attributes {
|
|
@@ -1798,6 +1879,75 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1798
1879
|
}
|
|
1799
1880
|
}
|
|
1800
1881
|
|
|
1882
|
+
- (UIMenu *)textView:(UITextView *)tv
|
|
1883
|
+
editMenuForTextInRange:(NSRange)range
|
|
1884
|
+
suggestedActions:(NSArray<UIMenuElement *> *)suggestedActions
|
|
1885
|
+
API_AVAILABLE(ios(16.0)) {
|
|
1886
|
+
if (_contextMenuItems == nil || _contextMenuItems.count == 0) {
|
|
1887
|
+
return [UIMenu menuWithChildren:suggestedActions];
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
NSMutableArray<UIMenuElement *> *customActions = [NSMutableArray new];
|
|
1891
|
+
|
|
1892
|
+
for (NSString *title in _contextMenuItems) {
|
|
1893
|
+
__weak EnrichedTextInputView *weakSelf = self;
|
|
1894
|
+
|
|
1895
|
+
UIAction *action =
|
|
1896
|
+
[UIAction actionWithTitle:title
|
|
1897
|
+
image:nil
|
|
1898
|
+
identifier:nil
|
|
1899
|
+
handler:^(__kindof UIAction *_Nonnull action) {
|
|
1900
|
+
[weakSelf emitOnContextMenuItemPressEvent:title];
|
|
1901
|
+
}];
|
|
1902
|
+
[customActions addObject:action];
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
[customActions addObjectsFromArray:suggestedActions];
|
|
1906
|
+
return [UIMenu menuWithChildren:customActions];
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
- (void)emitOnContextMenuItemPressEvent:(NSString *)itemText {
|
|
1910
|
+
auto emitter = [self getEventEmitter];
|
|
1911
|
+
if (emitter != nullptr) {
|
|
1912
|
+
NSRange selectedRange = textView.selectedRange;
|
|
1913
|
+
NSString *selectedText = @"";
|
|
1914
|
+
if (selectedRange.length > 0) {
|
|
1915
|
+
selectedText =
|
|
1916
|
+
[textView.textStorage.string substringWithRange:selectedRange];
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
emitter->onContextMenuItemPress(
|
|
1920
|
+
{.itemText = [itemText toCppString],
|
|
1921
|
+
.selectedText = [selectedText toCppString],
|
|
1922
|
+
.selectionStart = static_cast<int>(selectedRange.location),
|
|
1923
|
+
.selectionEnd =
|
|
1924
|
+
static_cast<int>(selectedRange.location + selectedRange.length),
|
|
1925
|
+
.styleState = {
|
|
1926
|
+
.bold = GET_STYLE_STATE([BoldStyle getStyleType]),
|
|
1927
|
+
.italic = GET_STYLE_STATE([ItalicStyle getStyleType]),
|
|
1928
|
+
.underline = GET_STYLE_STATE([UnderlineStyle getStyleType]),
|
|
1929
|
+
.strikeThrough =
|
|
1930
|
+
GET_STYLE_STATE([StrikethroughStyle getStyleType]),
|
|
1931
|
+
.inlineCode = GET_STYLE_STATE([InlineCodeStyle getStyleType]),
|
|
1932
|
+
.h1 = GET_STYLE_STATE([H1Style getStyleType]),
|
|
1933
|
+
.h2 = GET_STYLE_STATE([H2Style getStyleType]),
|
|
1934
|
+
.h3 = GET_STYLE_STATE([H3Style getStyleType]),
|
|
1935
|
+
.h4 = GET_STYLE_STATE([H4Style getStyleType]),
|
|
1936
|
+
.h5 = GET_STYLE_STATE([H5Style getStyleType]),
|
|
1937
|
+
.h6 = GET_STYLE_STATE([H6Style getStyleType]),
|
|
1938
|
+
.codeBlock = GET_STYLE_STATE([CodeBlockStyle getStyleType]),
|
|
1939
|
+
.blockQuote = GET_STYLE_STATE([BlockQuoteStyle getStyleType]),
|
|
1940
|
+
.orderedList = GET_STYLE_STATE([OrderedListStyle getStyleType]),
|
|
1941
|
+
.unorderedList =
|
|
1942
|
+
GET_STYLE_STATE([UnorderedListStyle getStyleType]),
|
|
1943
|
+
.link = GET_STYLE_STATE([LinkStyle getStyleType]),
|
|
1944
|
+
.image = GET_STYLE_STATE([ImageStyle getStyleType]),
|
|
1945
|
+
.mention = GET_STYLE_STATE([MentionStyle getStyleType]),
|
|
1946
|
+
.checkboxList =
|
|
1947
|
+
GET_STYLE_STATE([CheckboxListStyle getStyleType])}});
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1801
1951
|
- (void)handleKeyPressInRange:(NSString *)text range:(NSRange)range {
|
|
1802
1952
|
NSString *key = nil;
|
|
1803
1953
|
|
|
@@ -1884,6 +2034,14 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1884
2034
|
return NO;
|
|
1885
2035
|
}
|
|
1886
2036
|
|
|
2037
|
+
// Tapping near a link causes iOS to re-derive typingAttributes from
|
|
2038
|
+
// character attributes after textViewDidChangeSelection returns, undoing
|
|
2039
|
+
// the cleanup in manageSelectionBasedChanges. Strip them again here, right
|
|
2040
|
+
// before insertion, so new text never inherits link styling.
|
|
2041
|
+
if (linkStyle != nullptr) {
|
|
2042
|
+
[linkStyle manageLinkTypingAttributes];
|
|
2043
|
+
}
|
|
2044
|
+
|
|
1887
2045
|
return YES;
|
|
1888
2046
|
}
|
|
1889
2047
|
|
package/ios/config/InputConfig.h
CHANGED
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
- (void)setPrimaryColor:(UIColor *)newValue;
|
|
11
11
|
- (NSNumber *)primaryFontSize;
|
|
12
12
|
- (void)setPrimaryFontSize:(NSNumber *)newValue;
|
|
13
|
+
- (CGFloat)primaryLineHeight;
|
|
14
|
+
- (void)setPrimaryLineHeight:(CGFloat)newValue;
|
|
15
|
+
- (CGFloat)scaledPrimaryLineHeight;
|
|
13
16
|
- (NSString *)primaryFontWeight;
|
|
14
17
|
- (void)setPrimaryFontWeight:(NSString *)newValue;
|
|
15
18
|
- (NSString *)primaryFontFamily;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
@implementation InputConfig {
|
|
5
5
|
UIColor *_primaryColor;
|
|
6
6
|
NSNumber *_primaryFontSize;
|
|
7
|
+
CGFloat _primaryLineHeight;
|
|
7
8
|
NSString *_primaryFontWeight;
|
|
8
9
|
NSString *_primaryFontFamily;
|
|
9
10
|
UIFont *_primaryFont;
|
|
@@ -67,6 +68,7 @@
|
|
|
67
68
|
InputConfig *copy = [[[self class] allocWithZone:zone] init];
|
|
68
69
|
copy->_primaryColor = [_primaryColor copy];
|
|
69
70
|
copy->_primaryFontSize = [_primaryFontSize copy];
|
|
71
|
+
copy->_primaryLineHeight = _primaryLineHeight;
|
|
70
72
|
copy->_primaryFontWeight = [_primaryFontWeight copy];
|
|
71
73
|
copy->_primaryFontFamily = [_primaryFontFamily copy];
|
|
72
74
|
copy->_primaryFont = [_primaryFont copy];
|
|
@@ -135,6 +137,19 @@
|
|
|
135
137
|
_olMarkerFontNeedsRecreation = YES;
|
|
136
138
|
}
|
|
137
139
|
|
|
140
|
+
- (CGFloat)primaryLineHeight {
|
|
141
|
+
return _primaryLineHeight;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
- (void)setPrimaryLineHeight:(CGFloat)newValue {
|
|
145
|
+
_primaryLineHeight = newValue;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
- (CGFloat)scaledPrimaryLineHeight {
|
|
149
|
+
return [[UIFontMetrics defaultMetrics]
|
|
150
|
+
scaledValueForValue:[self primaryLineHeight]];
|
|
151
|
+
}
|
|
152
|
+
|
|
138
153
|
- (NSString *)primaryFontWeight {
|
|
139
154
|
return _primaryFontWeight != nullptr
|
|
140
155
|
? _primaryFontWeight
|
|
@@ -283,6 +283,18 @@ static void const *kInputKey = &kInputKey;
|
|
|
283
283
|
NSTextContainer *container,
|
|
284
284
|
NSRange lineGlyphRange,
|
|
285
285
|
BOOL *stop) {
|
|
286
|
+
NSUInteger charIdx =
|
|
287
|
+
[self characterIndexForGlyphAtIndex:
|
|
288
|
+
lineGlyphRange.location];
|
|
289
|
+
UIFont *font =
|
|
290
|
+
[typedInput->textView.textStorage
|
|
291
|
+
attribute:NSFontAttributeName
|
|
292
|
+
atIndex:charIdx
|
|
293
|
+
effectiveRange:nil];
|
|
294
|
+
CGRect textUsedRect =
|
|
295
|
+
[self getTextAlignedUsedRect:usedRect
|
|
296
|
+
font:font];
|
|
297
|
+
|
|
286
298
|
NSString *markerFormat =
|
|
287
299
|
pStyle.textLists.firstObject
|
|
288
300
|
.markerFormat;
|
|
@@ -291,27 +303,23 @@ static void const *kInputKey = &kInputKey;
|
|
|
291
303
|
NSTextListMarkerDecimal) {
|
|
292
304
|
NSString *marker = [self
|
|
293
305
|
getDecimalMarkerForList:typedInput
|
|
294
|
-
charIndex:
|
|
295
|
-
[self
|
|
296
|
-
characterIndexForGlyphAtIndex:
|
|
297
|
-
lineGlyphRange
|
|
298
|
-
.location]];
|
|
306
|
+
charIndex:charIdx];
|
|
299
307
|
[self drawDecimal:typedInput
|
|
300
308
|
marker:marker
|
|
301
309
|
markerAttributes:markerAttributes
|
|
302
310
|
origin:origin
|
|
303
|
-
usedRect:
|
|
311
|
+
usedRect:textUsedRect];
|
|
304
312
|
} else if (markerFormat ==
|
|
305
313
|
NSTextListMarkerDisc) {
|
|
306
314
|
[self drawBullet:typedInput
|
|
307
315
|
origin:origin
|
|
308
|
-
usedRect:
|
|
316
|
+
usedRect:textUsedRect];
|
|
309
317
|
} else if ([markerFormat
|
|
310
318
|
hasPrefix:@"{checkbox"]) {
|
|
311
319
|
[self drawCheckbox:typedInput
|
|
312
320
|
markerFormat:markerFormat
|
|
313
321
|
origin:origin
|
|
314
|
-
usedRect:
|
|
322
|
+
usedRect:textUsedRect];
|
|
315
323
|
}
|
|
316
324
|
// only first line of a list gets its
|
|
317
325
|
// marker drawn
|
|
@@ -363,6 +371,19 @@ static void const *kInputKey = &kInputKey;
|
|
|
363
371
|
return [NSString stringWithFormat:@"%ld.", (long)(itemNumber)];
|
|
364
372
|
}
|
|
365
373
|
|
|
374
|
+
// Returns a usedRect adjusted to cover only the text portion of the line.
|
|
375
|
+
// When minimumLineHeight expands the line box, extra space is added at the top
|
|
376
|
+
// and text stays at the bottom. This strips that padding so markers align with
|
|
377
|
+
// the text, not the full line box.
|
|
378
|
+
- (CGRect)getTextAlignedUsedRect:(CGRect)usedRect font:(UIFont *)font {
|
|
379
|
+
if (font && usedRect.size.height > font.lineHeight) {
|
|
380
|
+
CGFloat extraSpace = usedRect.size.height - font.lineHeight;
|
|
381
|
+
usedRect.origin.y += extraSpace;
|
|
382
|
+
usedRect.size.height = font.lineHeight;
|
|
383
|
+
}
|
|
384
|
+
return usedRect;
|
|
385
|
+
}
|
|
386
|
+
|
|
366
387
|
- (void)drawCheckbox:(EnrichedTextInputView *)typedInput
|
|
367
388
|
markerFormat:(NSString *)markerFormat
|
|
368
389
|
origin:(CGPoint)origin
|
|
@@ -406,10 +427,12 @@ static void const *kInputKey = &kInputKey;
|
|
|
406
427
|
origin:(CGPoint)origin
|
|
407
428
|
usedRect:(CGRect)usedRect {
|
|
408
429
|
CGFloat gapWidth = [typedInput->config orderedListGapWidth];
|
|
409
|
-
|
|
410
|
-
CGFloat markerX = usedRect.origin.x - gapWidth -
|
|
430
|
+
CGSize markerSize = [marker sizeWithAttributes:markerAttributes];
|
|
431
|
+
CGFloat markerX = usedRect.origin.x - gapWidth - markerSize.width / 2;
|
|
432
|
+
CGFloat centerY = CGRectGetMidY(usedRect) + origin.y;
|
|
433
|
+
CGFloat markerY = centerY - markerSize.height / 2.0;
|
|
411
434
|
|
|
412
|
-
[marker drawAtPoint:CGPointMake(markerX,
|
|
435
|
+
[marker drawAtPoint:CGPointMake(markerX, markerY)
|
|
413
436
|
withAttributes:markerAttributes];
|
|
414
437
|
}
|
|
415
438
|
|
|
@@ -273,4 +273,153 @@ imagesObject.setProperty(runtime, "height", imagesValue.height);
|
|
|
273
273
|
});
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
+
|
|
277
|
+
void EnrichedTextInputViewEventEmitter::onContextMenuItemPress(OnContextMenuItemPress event) const {
|
|
278
|
+
dispatchEvent("contextMenuItemPress", [event=std::move(event)](jsi::Runtime &runtime) {
|
|
279
|
+
auto payload = jsi::Object(runtime);
|
|
280
|
+
payload.setProperty(runtime, "itemText", event.itemText);
|
|
281
|
+
payload.setProperty(runtime, "selectedText", event.selectedText);
|
|
282
|
+
payload.setProperty(runtime, "selectionStart", event.selectionStart);
|
|
283
|
+
payload.setProperty(runtime, "selectionEnd", event.selectionEnd);
|
|
284
|
+
{
|
|
285
|
+
auto styleState = jsi::Object(runtime);
|
|
286
|
+
{
|
|
287
|
+
auto bold = jsi::Object(runtime);
|
|
288
|
+
bold.setProperty(runtime, "isActive", event.styleState.bold.isActive);
|
|
289
|
+
bold.setProperty(runtime, "isConflicting", event.styleState.bold.isConflicting);
|
|
290
|
+
bold.setProperty(runtime, "isBlocking", event.styleState.bold.isBlocking);
|
|
291
|
+
styleState.setProperty(runtime, "bold", bold);
|
|
292
|
+
}
|
|
293
|
+
{
|
|
294
|
+
auto italic = jsi::Object(runtime);
|
|
295
|
+
italic.setProperty(runtime, "isActive", event.styleState.italic.isActive);
|
|
296
|
+
italic.setProperty(runtime, "isConflicting", event.styleState.italic.isConflicting);
|
|
297
|
+
italic.setProperty(runtime, "isBlocking", event.styleState.italic.isBlocking);
|
|
298
|
+
styleState.setProperty(runtime, "italic", italic);
|
|
299
|
+
}
|
|
300
|
+
{
|
|
301
|
+
auto underline = jsi::Object(runtime);
|
|
302
|
+
underline.setProperty(runtime, "isActive", event.styleState.underline.isActive);
|
|
303
|
+
underline.setProperty(runtime, "isConflicting", event.styleState.underline.isConflicting);
|
|
304
|
+
underline.setProperty(runtime, "isBlocking", event.styleState.underline.isBlocking);
|
|
305
|
+
styleState.setProperty(runtime, "underline", underline);
|
|
306
|
+
}
|
|
307
|
+
{
|
|
308
|
+
auto strikeThrough = jsi::Object(runtime);
|
|
309
|
+
strikeThrough.setProperty(runtime, "isActive", event.styleState.strikeThrough.isActive);
|
|
310
|
+
strikeThrough.setProperty(runtime, "isConflicting", event.styleState.strikeThrough.isConflicting);
|
|
311
|
+
strikeThrough.setProperty(runtime, "isBlocking", event.styleState.strikeThrough.isBlocking);
|
|
312
|
+
styleState.setProperty(runtime, "strikeThrough", strikeThrough);
|
|
313
|
+
}
|
|
314
|
+
{
|
|
315
|
+
auto inlineCode = jsi::Object(runtime);
|
|
316
|
+
inlineCode.setProperty(runtime, "isActive", event.styleState.inlineCode.isActive);
|
|
317
|
+
inlineCode.setProperty(runtime, "isConflicting", event.styleState.inlineCode.isConflicting);
|
|
318
|
+
inlineCode.setProperty(runtime, "isBlocking", event.styleState.inlineCode.isBlocking);
|
|
319
|
+
styleState.setProperty(runtime, "inlineCode", inlineCode);
|
|
320
|
+
}
|
|
321
|
+
{
|
|
322
|
+
auto h1 = jsi::Object(runtime);
|
|
323
|
+
h1.setProperty(runtime, "isActive", event.styleState.h1.isActive);
|
|
324
|
+
h1.setProperty(runtime, "isConflicting", event.styleState.h1.isConflicting);
|
|
325
|
+
h1.setProperty(runtime, "isBlocking", event.styleState.h1.isBlocking);
|
|
326
|
+
styleState.setProperty(runtime, "h1", h1);
|
|
327
|
+
}
|
|
328
|
+
{
|
|
329
|
+
auto h2 = jsi::Object(runtime);
|
|
330
|
+
h2.setProperty(runtime, "isActive", event.styleState.h2.isActive);
|
|
331
|
+
h2.setProperty(runtime, "isConflicting", event.styleState.h2.isConflicting);
|
|
332
|
+
h2.setProperty(runtime, "isBlocking", event.styleState.h2.isBlocking);
|
|
333
|
+
styleState.setProperty(runtime, "h2", h2);
|
|
334
|
+
}
|
|
335
|
+
{
|
|
336
|
+
auto h3 = jsi::Object(runtime);
|
|
337
|
+
h3.setProperty(runtime, "isActive", event.styleState.h3.isActive);
|
|
338
|
+
h3.setProperty(runtime, "isConflicting", event.styleState.h3.isConflicting);
|
|
339
|
+
h3.setProperty(runtime, "isBlocking", event.styleState.h3.isBlocking);
|
|
340
|
+
styleState.setProperty(runtime, "h3", h3);
|
|
341
|
+
}
|
|
342
|
+
{
|
|
343
|
+
auto h4 = jsi::Object(runtime);
|
|
344
|
+
h4.setProperty(runtime, "isActive", event.styleState.h4.isActive);
|
|
345
|
+
h4.setProperty(runtime, "isConflicting", event.styleState.h4.isConflicting);
|
|
346
|
+
h4.setProperty(runtime, "isBlocking", event.styleState.h4.isBlocking);
|
|
347
|
+
styleState.setProperty(runtime, "h4", h4);
|
|
348
|
+
}
|
|
349
|
+
{
|
|
350
|
+
auto h5 = jsi::Object(runtime);
|
|
351
|
+
h5.setProperty(runtime, "isActive", event.styleState.h5.isActive);
|
|
352
|
+
h5.setProperty(runtime, "isConflicting", event.styleState.h5.isConflicting);
|
|
353
|
+
h5.setProperty(runtime, "isBlocking", event.styleState.h5.isBlocking);
|
|
354
|
+
styleState.setProperty(runtime, "h5", h5);
|
|
355
|
+
}
|
|
356
|
+
{
|
|
357
|
+
auto h6 = jsi::Object(runtime);
|
|
358
|
+
h6.setProperty(runtime, "isActive", event.styleState.h6.isActive);
|
|
359
|
+
h6.setProperty(runtime, "isConflicting", event.styleState.h6.isConflicting);
|
|
360
|
+
h6.setProperty(runtime, "isBlocking", event.styleState.h6.isBlocking);
|
|
361
|
+
styleState.setProperty(runtime, "h6", h6);
|
|
362
|
+
}
|
|
363
|
+
{
|
|
364
|
+
auto codeBlock = jsi::Object(runtime);
|
|
365
|
+
codeBlock.setProperty(runtime, "isActive", event.styleState.codeBlock.isActive);
|
|
366
|
+
codeBlock.setProperty(runtime, "isConflicting", event.styleState.codeBlock.isConflicting);
|
|
367
|
+
codeBlock.setProperty(runtime, "isBlocking", event.styleState.codeBlock.isBlocking);
|
|
368
|
+
styleState.setProperty(runtime, "codeBlock", codeBlock);
|
|
369
|
+
}
|
|
370
|
+
{
|
|
371
|
+
auto blockQuote = jsi::Object(runtime);
|
|
372
|
+
blockQuote.setProperty(runtime, "isActive", event.styleState.blockQuote.isActive);
|
|
373
|
+
blockQuote.setProperty(runtime, "isConflicting", event.styleState.blockQuote.isConflicting);
|
|
374
|
+
blockQuote.setProperty(runtime, "isBlocking", event.styleState.blockQuote.isBlocking);
|
|
375
|
+
styleState.setProperty(runtime, "blockQuote", blockQuote);
|
|
376
|
+
}
|
|
377
|
+
{
|
|
378
|
+
auto orderedList = jsi::Object(runtime);
|
|
379
|
+
orderedList.setProperty(runtime, "isActive", event.styleState.orderedList.isActive);
|
|
380
|
+
orderedList.setProperty(runtime, "isConflicting", event.styleState.orderedList.isConflicting);
|
|
381
|
+
orderedList.setProperty(runtime, "isBlocking", event.styleState.orderedList.isBlocking);
|
|
382
|
+
styleState.setProperty(runtime, "orderedList", orderedList);
|
|
383
|
+
}
|
|
384
|
+
{
|
|
385
|
+
auto unorderedList = jsi::Object(runtime);
|
|
386
|
+
unorderedList.setProperty(runtime, "isActive", event.styleState.unorderedList.isActive);
|
|
387
|
+
unorderedList.setProperty(runtime, "isConflicting", event.styleState.unorderedList.isConflicting);
|
|
388
|
+
unorderedList.setProperty(runtime, "isBlocking", event.styleState.unorderedList.isBlocking);
|
|
389
|
+
styleState.setProperty(runtime, "unorderedList", unorderedList);
|
|
390
|
+
}
|
|
391
|
+
{
|
|
392
|
+
auto link = jsi::Object(runtime);
|
|
393
|
+
link.setProperty(runtime, "isActive", event.styleState.link.isActive);
|
|
394
|
+
link.setProperty(runtime, "isConflicting", event.styleState.link.isConflicting);
|
|
395
|
+
link.setProperty(runtime, "isBlocking", event.styleState.link.isBlocking);
|
|
396
|
+
styleState.setProperty(runtime, "link", link);
|
|
397
|
+
}
|
|
398
|
+
{
|
|
399
|
+
auto image = jsi::Object(runtime);
|
|
400
|
+
image.setProperty(runtime, "isActive", event.styleState.image.isActive);
|
|
401
|
+
image.setProperty(runtime, "isConflicting", event.styleState.image.isConflicting);
|
|
402
|
+
image.setProperty(runtime, "isBlocking", event.styleState.image.isBlocking);
|
|
403
|
+
styleState.setProperty(runtime, "image", image);
|
|
404
|
+
}
|
|
405
|
+
{
|
|
406
|
+
auto mention = jsi::Object(runtime);
|
|
407
|
+
mention.setProperty(runtime, "isActive", event.styleState.mention.isActive);
|
|
408
|
+
mention.setProperty(runtime, "isConflicting", event.styleState.mention.isConflicting);
|
|
409
|
+
mention.setProperty(runtime, "isBlocking", event.styleState.mention.isBlocking);
|
|
410
|
+
styleState.setProperty(runtime, "mention", mention);
|
|
411
|
+
}
|
|
412
|
+
{
|
|
413
|
+
auto checkboxList = jsi::Object(runtime);
|
|
414
|
+
checkboxList.setProperty(runtime, "isActive", event.styleState.checkboxList.isActive);
|
|
415
|
+
checkboxList.setProperty(runtime, "isConflicting", event.styleState.checkboxList.isConflicting);
|
|
416
|
+
checkboxList.setProperty(runtime, "isBlocking", event.styleState.checkboxList.isBlocking);
|
|
417
|
+
styleState.setProperty(runtime, "checkboxList", checkboxList);
|
|
418
|
+
}
|
|
419
|
+
payload.setProperty(runtime, "styleState", styleState);
|
|
420
|
+
}
|
|
421
|
+
return payload;
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
|
|
276
425
|
} // namespace facebook::react
|
|
@@ -212,6 +212,150 @@ class EnrichedTextInputViewEventEmitter : public ViewEventEmitter {
|
|
|
212
212
|
struct OnPasteImages {
|
|
213
213
|
std::vector<OnPasteImagesImages> images;
|
|
214
214
|
};
|
|
215
|
+
|
|
216
|
+
struct OnContextMenuItemPressStyleStateBold {
|
|
217
|
+
bool isActive;
|
|
218
|
+
bool isConflicting;
|
|
219
|
+
bool isBlocking;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
struct OnContextMenuItemPressStyleStateItalic {
|
|
223
|
+
bool isActive;
|
|
224
|
+
bool isConflicting;
|
|
225
|
+
bool isBlocking;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
struct OnContextMenuItemPressStyleStateUnderline {
|
|
229
|
+
bool isActive;
|
|
230
|
+
bool isConflicting;
|
|
231
|
+
bool isBlocking;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
struct OnContextMenuItemPressStyleStateStrikeThrough {
|
|
235
|
+
bool isActive;
|
|
236
|
+
bool isConflicting;
|
|
237
|
+
bool isBlocking;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
struct OnContextMenuItemPressStyleStateInlineCode {
|
|
241
|
+
bool isActive;
|
|
242
|
+
bool isConflicting;
|
|
243
|
+
bool isBlocking;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
struct OnContextMenuItemPressStyleStateH1 {
|
|
247
|
+
bool isActive;
|
|
248
|
+
bool isConflicting;
|
|
249
|
+
bool isBlocking;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
struct OnContextMenuItemPressStyleStateH2 {
|
|
253
|
+
bool isActive;
|
|
254
|
+
bool isConflicting;
|
|
255
|
+
bool isBlocking;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
struct OnContextMenuItemPressStyleStateH3 {
|
|
259
|
+
bool isActive;
|
|
260
|
+
bool isConflicting;
|
|
261
|
+
bool isBlocking;
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
struct OnContextMenuItemPressStyleStateH4 {
|
|
265
|
+
bool isActive;
|
|
266
|
+
bool isConflicting;
|
|
267
|
+
bool isBlocking;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
struct OnContextMenuItemPressStyleStateH5 {
|
|
271
|
+
bool isActive;
|
|
272
|
+
bool isConflicting;
|
|
273
|
+
bool isBlocking;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
struct OnContextMenuItemPressStyleStateH6 {
|
|
277
|
+
bool isActive;
|
|
278
|
+
bool isConflicting;
|
|
279
|
+
bool isBlocking;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
struct OnContextMenuItemPressStyleStateCodeBlock {
|
|
283
|
+
bool isActive;
|
|
284
|
+
bool isConflicting;
|
|
285
|
+
bool isBlocking;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
struct OnContextMenuItemPressStyleStateBlockQuote {
|
|
289
|
+
bool isActive;
|
|
290
|
+
bool isConflicting;
|
|
291
|
+
bool isBlocking;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
struct OnContextMenuItemPressStyleStateOrderedList {
|
|
295
|
+
bool isActive;
|
|
296
|
+
bool isConflicting;
|
|
297
|
+
bool isBlocking;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
struct OnContextMenuItemPressStyleStateUnorderedList {
|
|
301
|
+
bool isActive;
|
|
302
|
+
bool isConflicting;
|
|
303
|
+
bool isBlocking;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
struct OnContextMenuItemPressStyleStateLink {
|
|
307
|
+
bool isActive;
|
|
308
|
+
bool isConflicting;
|
|
309
|
+
bool isBlocking;
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
struct OnContextMenuItemPressStyleStateImage {
|
|
313
|
+
bool isActive;
|
|
314
|
+
bool isConflicting;
|
|
315
|
+
bool isBlocking;
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
struct OnContextMenuItemPressStyleStateMention {
|
|
319
|
+
bool isActive;
|
|
320
|
+
bool isConflicting;
|
|
321
|
+
bool isBlocking;
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
struct OnContextMenuItemPressStyleStateCheckboxList {
|
|
325
|
+
bool isActive;
|
|
326
|
+
bool isConflicting;
|
|
327
|
+
bool isBlocking;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
struct OnContextMenuItemPressStyleState {
|
|
331
|
+
OnContextMenuItemPressStyleStateBold bold;
|
|
332
|
+
OnContextMenuItemPressStyleStateItalic italic;
|
|
333
|
+
OnContextMenuItemPressStyleStateUnderline underline;
|
|
334
|
+
OnContextMenuItemPressStyleStateStrikeThrough strikeThrough;
|
|
335
|
+
OnContextMenuItemPressStyleStateInlineCode inlineCode;
|
|
336
|
+
OnContextMenuItemPressStyleStateH1 h1;
|
|
337
|
+
OnContextMenuItemPressStyleStateH2 h2;
|
|
338
|
+
OnContextMenuItemPressStyleStateH3 h3;
|
|
339
|
+
OnContextMenuItemPressStyleStateH4 h4;
|
|
340
|
+
OnContextMenuItemPressStyleStateH5 h5;
|
|
341
|
+
OnContextMenuItemPressStyleStateH6 h6;
|
|
342
|
+
OnContextMenuItemPressStyleStateCodeBlock codeBlock;
|
|
343
|
+
OnContextMenuItemPressStyleStateBlockQuote blockQuote;
|
|
344
|
+
OnContextMenuItemPressStyleStateOrderedList orderedList;
|
|
345
|
+
OnContextMenuItemPressStyleStateUnorderedList unorderedList;
|
|
346
|
+
OnContextMenuItemPressStyleStateLink link;
|
|
347
|
+
OnContextMenuItemPressStyleStateImage image;
|
|
348
|
+
OnContextMenuItemPressStyleStateMention mention;
|
|
349
|
+
OnContextMenuItemPressStyleStateCheckboxList checkboxList;
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
struct OnContextMenuItemPress {
|
|
353
|
+
std::string itemText;
|
|
354
|
+
std::string selectedText;
|
|
355
|
+
int selectionStart;
|
|
356
|
+
int selectionEnd;
|
|
357
|
+
OnContextMenuItemPressStyleState styleState;
|
|
358
|
+
};
|
|
215
359
|
void onInputFocus(OnInputFocus value) const;
|
|
216
360
|
|
|
217
361
|
void onInputBlur(OnInputBlur value) const;
|
|
@@ -235,5 +379,7 @@ class EnrichedTextInputViewEventEmitter : public ViewEventEmitter {
|
|
|
235
379
|
void onInputKeyPress(OnInputKeyPress value) const;
|
|
236
380
|
|
|
237
381
|
void onPasteImages(OnPasteImages value) const;
|
|
382
|
+
|
|
383
|
+
void onContextMenuItemPress(OnContextMenuItemPress value) const;
|
|
238
384
|
};
|
|
239
385
|
} // namespace facebook::react
|