mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-03-26 07:04:05 +08:00
Updates from Fri Feb 27
- [react-packager] transformModulePath option is not actually required | Amjad Masad - Implement TextInput.clearButtonMode added by D1875684 on OSS fork + example | Tadeu Zagallo - [ReactNative] Use local CocoaPod config for ReactNative modules | Spencer Ahrens - [ReactNative] Pull out some OSS modules into separate libs | Spencer Ahrens - Enqueue events at 60fps + profiling helpers | Tadeu Zagallo
This commit is contained in:
120
Libraries/Text/ExpandingText.js
Normal file
120
Libraries/Text/ExpandingText.js
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ExpandingText
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var Text = require('Text');
|
||||
var TouchableWithoutFeedback = require('TouchableWithoutFeedback');
|
||||
var View = require('View');
|
||||
|
||||
var truncate = require('truncate');
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
boldText: {
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* <ExpandingText> - A react component for displaying text which supports truncating
|
||||
* based on a set truncLength. In the following example, the text will truncate
|
||||
* to show only the first 17 characters plus '...' with a See More button to
|
||||
* expand the text to its full length
|
||||
*
|
||||
* renderText: function() {
|
||||
* return <ExpandingText truncLength={20} text={EXAMPLE_TEXT} />;
|
||||
* },
|
||||
*
|
||||
* More example code in `ExpandingTextExample.js`
|
||||
*/
|
||||
var ExpandingText = React.createClass({
|
||||
PropTypes: {
|
||||
/**
|
||||
* Text to be displayed. Text will be truncated if the character length
|
||||
* is greater than the truncLength property.
|
||||
*/
|
||||
text: React.PropTypes.string.isRequired,
|
||||
/**
|
||||
* The styles that will be applied to the text (both truncated and expanded).
|
||||
*/
|
||||
textStyle: Text.stylePropType,
|
||||
/**
|
||||
* The styles that will be applied to the See More button
|
||||
*/
|
||||
seeMoreStyle: Text.stylePropType,
|
||||
/**
|
||||
* The maximum character length for the text that will
|
||||
* be displayed by default. Note that ... will be
|
||||
* appended to the truncated text which is counted towards
|
||||
* the total truncLength of the default displayed string
|
||||
*/
|
||||
truncLength: React.PropTypes.number
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
truncLength: 130,
|
||||
seeMoreText: 'See More',
|
||||
seeMoreStyle: styles.boldText,
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
truncated: true,
|
||||
};
|
||||
},
|
||||
|
||||
onTapSeeMore: function() {
|
||||
this.setState({
|
||||
truncated: !this.state.truncated,
|
||||
});
|
||||
},
|
||||
|
||||
isTruncated: function() {
|
||||
return (
|
||||
this.props.text.length > this.props.truncLength &&
|
||||
this.state.truncated
|
||||
);
|
||||
},
|
||||
|
||||
getText: function() {
|
||||
var text = this.props.text;
|
||||
if (!this.isTruncated()) {
|
||||
return text;
|
||||
}
|
||||
|
||||
return truncate(text, this.props.truncLength) + ' ';
|
||||
},
|
||||
|
||||
renderSeeMore: function() {
|
||||
if (!this.isTruncated()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Text style={this.props.seeMoreStyle}>
|
||||
{this.props.seeMoreText}
|
||||
</Text>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<TouchableWithoutFeedback onPress={this.onTapSeeMore}>
|
||||
<View>
|
||||
<Text style={this.props.textStyle}>
|
||||
{this.getText()}
|
||||
{this.renderSeeMore()}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ExpandingText;
|
||||
7
Libraries/Text/RCTRawTextManager.h
Normal file
7
Libraries/Text/RCTRawTextManager.h
Normal file
@@ -0,0 +1,7 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTViewManager.h"
|
||||
|
||||
@interface RCTRawTextManager : RCTViewManager
|
||||
|
||||
@end
|
||||
20
Libraries/Text/RCTRawTextManager.m
Normal file
20
Libraries/Text/RCTRawTextManager.m
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTRawTextManager.h"
|
||||
|
||||
#import "RCTShadowRawText.h"
|
||||
|
||||
@implementation RCTRawTextManager
|
||||
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[UIView alloc] init];
|
||||
}
|
||||
|
||||
- (RCTShadowView *)shadowView
|
||||
{
|
||||
return [[RCTShadowRawText alloc] init];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
9
Libraries/Text/RCTShadowRawText.h
Normal file
9
Libraries/Text/RCTShadowRawText.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTShadowView.h"
|
||||
|
||||
@interface RCTShadowRawText : RCTShadowView
|
||||
|
||||
@property (nonatomic, copy) NSString *text;
|
||||
|
||||
@end
|
||||
16
Libraries/Text/RCTShadowRawText.m
Normal file
16
Libraries/Text/RCTShadowRawText.m
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTShadowRawText.h"
|
||||
|
||||
@implementation RCTShadowRawText
|
||||
|
||||
- (void)setText:(NSString *)text
|
||||
{
|
||||
if (_text != text) {
|
||||
_text = [text copy];
|
||||
[self dirtyLayout];
|
||||
[self dirtyText];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
26
Libraries/Text/RCTShadowText.h
Normal file
26
Libraries/Text/RCTShadowText.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTShadowView.h"
|
||||
|
||||
extern NSString *const RCTIsHighlightedAttributeName;
|
||||
extern NSString *const RCTReactTagAttributeName;
|
||||
|
||||
@interface RCTShadowText : RCTShadowView
|
||||
|
||||
@property (nonatomic, assign) NSWritingDirection writingDirection;
|
||||
@property (nonatomic, strong) UIColor *textBackgroundColor;
|
||||
@property (nonatomic, strong) UIColor *color;
|
||||
@property (nonatomic, strong) UIFont *font;
|
||||
@property (nonatomic, copy) NSString *fontFamily;
|
||||
@property (nonatomic, assign) CGFloat fontSize;
|
||||
@property (nonatomic, copy) NSString *fontWeight;
|
||||
@property (nonatomic, assign) BOOL isHighlighted;
|
||||
@property (nonatomic, assign) CGFloat lineHeight;
|
||||
@property (nonatomic, assign) NSInteger maxNumberOfLines;
|
||||
@property (nonatomic, assign) CGSize shadowOffset;
|
||||
@property (nonatomic, assign) NSTextAlignment textAlign;
|
||||
@property (nonatomic, assign) NSLineBreakMode truncationMode;
|
||||
|
||||
- (NSAttributedString *)attributedString;
|
||||
|
||||
@end
|
||||
199
Libraries/Text/RCTShadowText.m
Normal file
199
Libraries/Text/RCTShadowText.m
Normal file
@@ -0,0 +1,199 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTShadowText.h"
|
||||
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTLog.h"
|
||||
|
||||
#import "RCTShadowRawText.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
NSString *const RCTIsHighlightedAttributeName = @"IsHighlightedAttributeName";
|
||||
NSString *const RCTReactTagAttributeName = @"ReactTagAttributeName";
|
||||
|
||||
static css_dim_t RCTMeasure(void *context, float width)
|
||||
{
|
||||
RCTShadowText *shadowText = (__bridge RCTShadowText *)context;
|
||||
CGSize computedSize = [[shadowText attributedString] boundingRectWithSize:(CGSize){isnan(width) ? CGFLOAT_MAX : width, CGFLOAT_MAX} options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
|
||||
|
||||
css_dim_t result;
|
||||
result.dimensions[CSS_WIDTH] = RCTCeilPixelValue(computedSize.width);
|
||||
result.dimensions[CSS_HEIGHT] = RCTCeilPixelValue(computedSize.height);
|
||||
return result;
|
||||
}
|
||||
|
||||
@implementation RCTShadowText
|
||||
{
|
||||
NSAttributedString *_cachedAttributedString;
|
||||
UIFont *_font;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_fontSize = NAN;
|
||||
_isHighlighted = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSAttributedString *)attributedString
|
||||
{
|
||||
return [self _attributedStringWithFontFamily:nil
|
||||
fontSize:0
|
||||
fontWeight:nil];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)_attributedStringWithFontFamily:(NSString *)fontFamily
|
||||
fontSize:(CGFloat)fontSize
|
||||
fontWeight:(NSString *)fontWeight
|
||||
{
|
||||
if (![self isTextDirty] && _cachedAttributedString) {
|
||||
return _cachedAttributedString;
|
||||
}
|
||||
|
||||
if (_fontSize && !isnan(_fontSize)) {
|
||||
fontSize = _fontSize;
|
||||
}
|
||||
if (_fontWeight) {
|
||||
fontWeight = _fontWeight;
|
||||
}
|
||||
if (_fontFamily) {
|
||||
fontFamily = _fontFamily;
|
||||
}
|
||||
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
|
||||
for (RCTShadowView *child in [self reactSubviews]) {
|
||||
if ([child isKindOfClass:[RCTShadowText class]]) {
|
||||
RCTShadowText *shadowText = (RCTShadowText *)child;
|
||||
[attributedString appendAttributedString:[shadowText _attributedStringWithFontFamily:fontFamily fontSize:fontSize fontWeight:fontWeight]];
|
||||
} else if ([child isKindOfClass:[RCTShadowRawText class]]) {
|
||||
RCTShadowRawText *shadowRawText = (RCTShadowRawText *)child;
|
||||
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:[shadowRawText text] ?: @""]];
|
||||
} else {
|
||||
RCTLogError(@"<Text> can't have any children except <Text> or raw strings");
|
||||
}
|
||||
|
||||
[child setTextComputed];
|
||||
}
|
||||
|
||||
if (_color) {
|
||||
[self _addAttribute:NSForegroundColorAttributeName withValue:self.color toAttributedString:attributedString];
|
||||
}
|
||||
if (_isHighlighted) {
|
||||
[self _addAttribute:RCTIsHighlightedAttributeName withValue:@YES toAttributedString:attributedString];
|
||||
}
|
||||
if (_textBackgroundColor) {
|
||||
[self _addAttribute:NSBackgroundColorAttributeName withValue:self.textBackgroundColor toAttributedString:attributedString];
|
||||
}
|
||||
|
||||
_font = [RCTConvert UIFont:nil withFamily:fontFamily size:@(fontSize) weight:fontWeight];
|
||||
[self _addAttribute:NSFontAttributeName withValue:_font toAttributedString:attributedString];
|
||||
[self _addAttribute:RCTReactTagAttributeName withValue:self.reactTag toAttributedString:attributedString];
|
||||
[self _setParagraphStyleOnAttributedString:attributedString];
|
||||
|
||||
// create a non-mutable attributedString for use by the Text system which avoids copies down the line
|
||||
_cachedAttributedString = [[NSAttributedString alloc] initWithAttributedString:attributedString];
|
||||
[self dirtyLayout];
|
||||
|
||||
return _cachedAttributedString;
|
||||
}
|
||||
|
||||
- (UIFont *)font
|
||||
{
|
||||
return _font ?: [RCTConvert UIFont:nil withFamily:_fontFamily size:@(_fontSize) weight:_fontWeight];
|
||||
}
|
||||
|
||||
- (void)_addAttribute:(NSString *)attribute withValue:(id)attributeValue toAttributedString:(NSMutableAttributedString *)attributedString
|
||||
{
|
||||
[attributedString enumerateAttribute:attribute inRange:NSMakeRange(0, [attributedString length]) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
|
||||
if (!value) {
|
||||
[attributedString addAttribute:attribute value:attributeValue range:range];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
/*
|
||||
* LineHeight works the same way line-height works in the web: if children and self have
|
||||
* varying lineHeights, we simply take the max.
|
||||
*/
|
||||
- (void)_setParagraphStyleOnAttributedString:(NSMutableAttributedString *)attributedString
|
||||
{
|
||||
// check if we have lineHeight set on self
|
||||
__block BOOL hasParagraphStyle = NO;
|
||||
if (_lineHeight || _textAlign) {
|
||||
hasParagraphStyle = YES;
|
||||
}
|
||||
|
||||
if (!_lineHeight) {
|
||||
self.lineHeight = 0.0;
|
||||
}
|
||||
|
||||
// check for lineHeight on each of our children, update the max as we go (in self.lineHeight)
|
||||
[attributedString enumerateAttribute:NSParagraphStyleAttributeName inRange:NSMakeRange(0, [attributedString length]) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
|
||||
if (value) {
|
||||
NSParagraphStyle *paragraphStyle = (NSParagraphStyle *)value;
|
||||
if ([paragraphStyle maximumLineHeight] > _lineHeight) {
|
||||
self.lineHeight = [paragraphStyle maximumLineHeight];
|
||||
}
|
||||
hasParagraphStyle = YES;
|
||||
}
|
||||
}];
|
||||
|
||||
// TODO: umm, these can'e be null, so we're mapping left to natural - is that right?
|
||||
self.textAlign = _textAlign ?: NSTextAlignmentNatural;
|
||||
self.writingDirection = _writingDirection ?: NSWritingDirectionNatural;
|
||||
|
||||
// if we found anything, set it :D
|
||||
if (hasParagraphStyle) {
|
||||
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
|
||||
paragraphStyle.alignment = _textAlign;
|
||||
paragraphStyle.baseWritingDirection = _writingDirection;
|
||||
paragraphStyle.minimumLineHeight = _lineHeight;
|
||||
paragraphStyle.maximumLineHeight = _lineHeight;
|
||||
[attributedString addAttribute:NSParagraphStyleAttributeName
|
||||
value:paragraphStyle
|
||||
range:(NSRange){0, attributedString.length}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)fillCSSNode:(css_node_t *)node
|
||||
{
|
||||
[super fillCSSNode:node];
|
||||
node->measure = RCTMeasure;
|
||||
node->children_count = 0;
|
||||
}
|
||||
|
||||
- (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)atIndex
|
||||
{
|
||||
[super insertReactSubview:subview atIndex:atIndex];
|
||||
[self cssNode]->children_count = 0;
|
||||
}
|
||||
|
||||
- (void)removeReactSubview:(RCTShadowView *)subview
|
||||
{
|
||||
[super removeReactSubview:subview];
|
||||
[self cssNode]->children_count = 0;
|
||||
}
|
||||
|
||||
#define RCT_TEXT_PROPERTY(setProp, ivar, type) \
|
||||
- (void)set##setProp:(type)value; \
|
||||
{ \
|
||||
ivar = value; \
|
||||
[self dirtyText]; \
|
||||
}
|
||||
|
||||
RCT_TEXT_PROPERTY(TextBackgroundColor, _textBackgroundColor, UIColor *);
|
||||
RCT_TEXT_PROPERTY(Color, _color, UIColor *);
|
||||
RCT_TEXT_PROPERTY(FontFamily, _fontFamily, NSString *);
|
||||
RCT_TEXT_PROPERTY(FontSize, _fontSize, CGFloat);
|
||||
RCT_TEXT_PROPERTY(FontWeight, _fontWeight, NSString *);
|
||||
RCT_TEXT_PROPERTY(LineHeight, _lineHeight, CGFloat);
|
||||
RCT_TEXT_PROPERTY(MaxNumberOfLines, _maxNumberOfLines, NSInteger);
|
||||
RCT_TEXT_PROPERTY(ShadowOffset, _shadowOffset, CGSize);
|
||||
RCT_TEXT_PROPERTY(TextAlign, _textAlign, NSTextAlignment);
|
||||
RCT_TEXT_PROPERTY(TruncationMode, _truncationMode, NSLineBreakMode);
|
||||
RCT_TEXT_PROPERTY(IsHighlighted, _isHighlighted, BOOL);
|
||||
RCT_TEXT_PROPERTY(Font, _font, UIFont *);
|
||||
|
||||
@end
|
||||
13
Libraries/Text/RCTText.h
Normal file
13
Libraries/Text/RCTText.h
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface RCTText : UIView
|
||||
|
||||
@property (nonatomic, copy) NSAttributedString *attributedText;
|
||||
@property (nonatomic, assign) NSLineBreakMode lineBreakMode;
|
||||
@property (nonatomic, assign) NSUInteger numberOfLines;
|
||||
|
||||
- (NSNumber *)reactTagAtPoint:(CGPoint)point;
|
||||
|
||||
@end
|
||||
100
Libraries/Text/RCTText.m
Normal file
100
Libraries/Text/RCTText.m
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTText.h"
|
||||
|
||||
#import "RCTShadowText.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "UIView+ReactKit.h"
|
||||
|
||||
@implementation RCTText
|
||||
{
|
||||
NSLayoutManager *_layoutManager;
|
||||
NSTextStorage *_textStorage;
|
||||
NSTextContainer *_textContainer;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
_textContainer = [[NSTextContainer alloc] init];
|
||||
_textContainer.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
_textContainer.lineFragmentPadding = 0.0;
|
||||
|
||||
_layoutManager = [[NSLayoutManager alloc] init];
|
||||
[_layoutManager addTextContainer:_textContainer];
|
||||
|
||||
_textStorage = [[NSTextStorage alloc] init];
|
||||
[_textStorage addLayoutManager:_layoutManager];
|
||||
|
||||
self.contentMode = UIViewContentModeRedraw;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSAttributedString *)attributedText
|
||||
{
|
||||
return [_textStorage copy];
|
||||
}
|
||||
|
||||
- (void)setAttributedText:(NSAttributedString *)attributedText
|
||||
{
|
||||
[_textStorage setAttributedString:attributedText];
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (NSUInteger)numberOfLines
|
||||
{
|
||||
return _textContainer.maximumNumberOfLines;
|
||||
}
|
||||
|
||||
- (void)setNumberOfLines:(NSUInteger)numberOfLines
|
||||
{
|
||||
_textContainer.maximumNumberOfLines = numberOfLines;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (NSLineBreakMode)lineBreakMode
|
||||
{
|
||||
return _textContainer.lineBreakMode;
|
||||
}
|
||||
|
||||
- (void)setLineBreakMode:(NSLineBreakMode)lineBreakMode
|
||||
{
|
||||
_textContainer.lineBreakMode = lineBreakMode;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
// The header comment for `size` says that a height of 0.0 should be enough,
|
||||
// but it isn't.
|
||||
_textContainer.size = CGSizeMake(self.bounds.size.width, CGFLOAT_MAX);
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
NSRange glyphRange = [_layoutManager glyphRangeForTextContainer:_textContainer];
|
||||
[_layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:CGPointZero];
|
||||
[_layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:CGPointZero];
|
||||
}
|
||||
|
||||
- (NSNumber *)reactTagAtPoint:(CGPoint)point
|
||||
{
|
||||
CGFloat fraction;
|
||||
NSUInteger characterIndex = [_layoutManager characterIndexForPoint:point inTextContainer:_textContainer fractionOfDistanceBetweenInsertionPoints:&fraction];
|
||||
|
||||
NSNumber *reactTag = nil;
|
||||
|
||||
// If the point is not before (fraction == 0.0) the first character and not
|
||||
// after (fraction == 1.0) the last character, then the attribute is valid.
|
||||
if (_textStorage.length > 0 && (fraction > 0 || characterIndex > 0) && (fraction < 1 || characterIndex < _textStorage.length - 1)) {
|
||||
reactTag = [_textStorage attribute:RCTReactTagAttributeName atIndex:characterIndex effectiveRange:NULL];
|
||||
}
|
||||
|
||||
return reactTag ?: self.reactTag;
|
||||
}
|
||||
|
||||
@end
|
||||
28
Libraries/Text/RCTText.podspec
Normal file
28
Libraries/Text/RCTText.podspec
Normal file
@@ -0,0 +1,28 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = 'RCTText'
|
||||
spec.version = '0.0.1'
|
||||
spec.summary = 'Provides basic Text capabilities in ReactNative apps.'
|
||||
spec.description = <<-DESC
|
||||
Text can be rendered in ReactNative apps with the <Text> component using this module.
|
||||
DESC
|
||||
spec.homepage = 'https://facebook.github.io/react-native/'
|
||||
spec.license = { :type => 'BSD' }
|
||||
spec.author = 'Facebook'
|
||||
spec.platform = :ios, '7.0'
|
||||
spec.requires_arc = true
|
||||
spec.source_files = '**/*.{h,m,c}'
|
||||
spec.dependency "ReactKit", "~> 0.0.1"
|
||||
|
||||
# ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# Link your library with frameworks, or libraries. Libraries do not include
|
||||
# the lib prefix of their name.
|
||||
#
|
||||
|
||||
# s.framework = "SomeFramework"
|
||||
# s.frameworks = "SomeFramework", "AnotherFramework"
|
||||
|
||||
# s.library = "iconv"
|
||||
#spec.libraries = "RCTText", "ReactKit"
|
||||
|
||||
end
|
||||
379
Libraries/Text/RCTText.xcodeproj/project.pbxproj
Normal file
379
Libraries/Text/RCTText.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,379 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
58B511A71A9E6C1300147676 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58B5119B1A9E6C1200147676 /* libRCTText.a */; };
|
||||
58B511CE1A9E6C5C00147676 /* RCTRawTextManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511C71A9E6C5C00147676 /* RCTRawTextManager.m */; };
|
||||
58B511CF1A9E6C5C00147676 /* RCTShadowRawText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511C91A9E6C5C00147676 /* RCTShadowRawText.m */; };
|
||||
58B511D01A9E6C5C00147676 /* RCTShadowText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511CB1A9E6C5C00147676 /* RCTShadowText.m */; };
|
||||
58B511D11A9E6C5C00147676 /* RCTTextManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511CD1A9E6C5C00147676 /* RCTTextManager.m */; };
|
||||
58B512161A9E6EFF00147676 /* RCTText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B512141A9E6EFF00147676 /* RCTText.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
58B511A81A9E6C1300147676 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 58B511931A9E6C1200147676 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 58B5119A1A9E6C1200147676;
|
||||
remoteInfo = RCTText;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
58B511991A9E6C1200147676 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "include/$(PRODUCT_NAME)";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
58B5119B1A9E6C1200147676 /* libRCTText.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTText.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
58B511A61A9E6C1300147676 /* RCTTextTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RCTTextTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
58B511C61A9E6C5C00147676 /* RCTRawTextManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRawTextManager.h; sourceTree = "<group>"; };
|
||||
58B511C71A9E6C5C00147676 /* RCTRawTextManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRawTextManager.m; sourceTree = "<group>"; };
|
||||
58B511C81A9E6C5C00147676 /* RCTShadowRawText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTShadowRawText.h; sourceTree = "<group>"; };
|
||||
58B511C91A9E6C5C00147676 /* RCTShadowRawText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTShadowRawText.m; sourceTree = "<group>"; };
|
||||
58B511CA1A9E6C5C00147676 /* RCTShadowText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTShadowText.h; sourceTree = "<group>"; };
|
||||
58B511CB1A9E6C5C00147676 /* RCTShadowText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTShadowText.m; sourceTree = "<group>"; };
|
||||
58B511CC1A9E6C5C00147676 /* RCTTextManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTextManager.h; sourceTree = "<group>"; };
|
||||
58B511CD1A9E6C5C00147676 /* RCTTextManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTextManager.m; sourceTree = "<group>"; };
|
||||
58B512141A9E6EFF00147676 /* RCTText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTText.m; sourceTree = "<group>"; };
|
||||
58B512151A9E6EFF00147676 /* RCTText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTText.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
58B511981A9E6C1200147676 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
58B511A31A9E6C1300147676 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
58B511A71A9E6C1300147676 /* libRCTText.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
58B511921A9E6C1200147676 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
58B511C61A9E6C5C00147676 /* RCTRawTextManager.h */,
|
||||
58B511C71A9E6C5C00147676 /* RCTRawTextManager.m */,
|
||||
58B511C81A9E6C5C00147676 /* RCTShadowRawText.h */,
|
||||
58B511C91A9E6C5C00147676 /* RCTShadowRawText.m */,
|
||||
58B511CA1A9E6C5C00147676 /* RCTShadowText.h */,
|
||||
58B511CB1A9E6C5C00147676 /* RCTShadowText.m */,
|
||||
58B512151A9E6EFF00147676 /* RCTText.h */,
|
||||
58B512141A9E6EFF00147676 /* RCTText.m */,
|
||||
58B511CC1A9E6C5C00147676 /* RCTTextManager.h */,
|
||||
58B511CD1A9E6C5C00147676 /* RCTTextManager.m */,
|
||||
58B5119C1A9E6C1200147676 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
58B5119C1A9E6C1200147676 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
58B5119B1A9E6C1200147676 /* libRCTText.a */,
|
||||
58B511A61A9E6C1300147676 /* RCTTextTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
58B5119A1A9E6C1200147676 /* RCTText */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 58B511AF1A9E6C1300147676 /* Build configuration list for PBXNativeTarget "RCTText" */;
|
||||
buildPhases = (
|
||||
58B511971A9E6C1200147676 /* Sources */,
|
||||
58B511981A9E6C1200147676 /* Frameworks */,
|
||||
58B511991A9E6C1200147676 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = RCTText;
|
||||
productName = RCTText;
|
||||
productReference = 58B5119B1A9E6C1200147676 /* libRCTText.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
58B511A51A9E6C1300147676 /* RCTTextTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 58B511B21A9E6C1300147676 /* Build configuration list for PBXNativeTarget "RCTTextTests" */;
|
||||
buildPhases = (
|
||||
58B511A21A9E6C1300147676 /* Sources */,
|
||||
58B511A31A9E6C1300147676 /* Frameworks */,
|
||||
58B511A41A9E6C1300147676 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
58B511A91A9E6C1300147676 /* PBXTargetDependency */,
|
||||
);
|
||||
name = RCTTextTests;
|
||||
productName = RCTTextTests;
|
||||
productReference = 58B511A61A9E6C1300147676 /* RCTTextTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
58B511931A9E6C1200147676 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
58B5119A1A9E6C1200147676 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
58B511A51A9E6C1300147676 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 58B511961A9E6C1200147676 /* Build configuration list for PBXProject "RCTText" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 58B511921A9E6C1200147676;
|
||||
productRefGroup = 58B5119C1A9E6C1200147676 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
58B5119A1A9E6C1200147676 /* RCTText */,
|
||||
58B511A51A9E6C1300147676 /* RCTTextTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
58B511A41A9E6C1300147676 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
58B511971A9E6C1200147676 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
58B511D11A9E6C5C00147676 /* RCTTextManager.m in Sources */,
|
||||
58B511CE1A9E6C5C00147676 /* RCTRawTextManager.m in Sources */,
|
||||
58B512161A9E6EFF00147676 /* RCTText.m in Sources */,
|
||||
58B511CF1A9E6C5C00147676 /* RCTShadowRawText.m in Sources */,
|
||||
58B511D01A9E6C5C00147676 /* RCTShadowText.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
58B511A21A9E6C1300147676 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
58B511A91A9E6C1300147676 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 58B5119A1A9E6C1200147676 /* RCTText */;
|
||||
targetProxy = 58B511A81A9E6C1300147676 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
58B511AD1A9E6C1300147676 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
58B511AE1A9E6C1300147676 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
58B511B01A9E6C1300147676 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
58B511B11A9E6C1300147676 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
58B511B31A9E6C1300147676 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = RCTTextTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
58B511B41A9E6C1300147676 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = RCTTextTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
58B511961A9E6C1200147676 /* Build configuration list for PBXProject "RCTText" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
58B511AD1A9E6C1300147676 /* Debug */,
|
||||
58B511AE1A9E6C1300147676 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
58B511AF1A9E6C1300147676 /* Build configuration list for PBXNativeTarget "RCTText" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
58B511B01A9E6C1300147676 /* Debug */,
|
||||
58B511B11A9E6C1300147676 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
58B511B21A9E6C1300147676 /* Build configuration list for PBXNativeTarget "RCTTextTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
58B511B31A9E6C1300147676 /* Debug */,
|
||||
58B511B41A9E6C1300147676 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 58B511931A9E6C1200147676 /* Project object */;
|
||||
}
|
||||
8
Libraries/Text/RCTTextManager.h
Normal file
8
Libraries/Text/RCTTextManager.h
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTViewManager.h"
|
||||
|
||||
@interface RCTTextManager : RCTViewManager
|
||||
|
||||
@end
|
||||
|
||||
135
Libraries/Text/RCTTextManager.m
Normal file
135
Libraries/Text/RCTTextManager.m
Normal file
@@ -0,0 +1,135 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTTextManager.h"
|
||||
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTShadowRawText.h"
|
||||
#import "RCTShadowText.h"
|
||||
#import "RCTSparseArray.h"
|
||||
#import "RCTText.h"
|
||||
#import "UIView+ReactKit.h"
|
||||
|
||||
@implementation RCTTextManager
|
||||
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[RCTText alloc] init];
|
||||
}
|
||||
|
||||
- (RCTShadowView *)shadowView
|
||||
{
|
||||
return [[RCTShadowText alloc] init];
|
||||
}
|
||||
|
||||
RCT_REMAP_VIEW_PROPERTY(containerBackgroundColor, backgroundColor)
|
||||
|
||||
- (void)set_textAlign:(id)json
|
||||
forShadowView:(RCTShadowText *)shadowView
|
||||
withDefaultView:(RCTShadowText *)defaultView
|
||||
{
|
||||
shadowView.textAlign = json ? [RCTConvert NSTextAlignment:json] : defaultView.textAlign;
|
||||
}
|
||||
|
||||
- (void)set_numberOfLines:(id)json
|
||||
forView:(RCTText *)view
|
||||
withDefaultView:(RCTText *)defaultView
|
||||
{
|
||||
NSLineBreakMode truncationMode = NSLineBreakByClipping;
|
||||
view.numberOfLines = json ? [RCTConvert NSInteger:json] : defaultView.numberOfLines;
|
||||
if (view.numberOfLines > 0) {
|
||||
truncationMode = NSLineBreakByTruncatingTail;
|
||||
}
|
||||
view.lineBreakMode = truncationMode;
|
||||
}
|
||||
|
||||
- (void)set_numberOfLines:(id)json
|
||||
forShadowView:(RCTShadowText *)shadowView
|
||||
withDefaultView:(RCTShadowText *)defaultView
|
||||
{
|
||||
NSLineBreakMode truncationMode = NSLineBreakByClipping;
|
||||
shadowView.maxNumberOfLines = json ? [RCTConvert NSInteger:json] : defaultView.maxNumberOfLines;
|
||||
if (shadowView.maxNumberOfLines > 0) {
|
||||
truncationMode = NSLineBreakByTruncatingTail;
|
||||
}
|
||||
shadowView.truncationMode = truncationMode;
|
||||
}
|
||||
|
||||
- (void)set_backgroundColor:(id)json
|
||||
forShadowView:(RCTShadowText *)shadowView
|
||||
withDefaultView:(RCTShadowText *)defaultView
|
||||
{
|
||||
shadowView.textBackgroundColor = json ? [RCTConvert UIColor:json] : defaultView.textBackgroundColor;
|
||||
}
|
||||
|
||||
- (void)set_containerBackgroundColor:(id)json
|
||||
forShadowView:(RCTShadowText *)shadowView
|
||||
withDefaultView:(RCTShadowText *)defaultView
|
||||
{
|
||||
shadowView.backgroundColor = json ? [RCTConvert UIColor:json] : defaultView.backgroundColor;
|
||||
shadowView.isBGColorExplicitlySet = json ? YES : defaultView.isBGColorExplicitlySet;
|
||||
}
|
||||
|
||||
// TODO: the purpose of this block is effectively just to copy properties from the shadow views
|
||||
// to their equivalent UIViews. In this case, the property being copied is the attributed text,
|
||||
// but the same principle could be used to copy any property. The implementation is really ugly tho
|
||||
// because the RCTViewManager doesn't retain a reference to the views that it manages, so it basically
|
||||
// has to search the entire view hierarchy for relevant views. Not awesome. This seems like something
|
||||
// where we could introduce a generic solution - perhaps a method on RCTShadowView that is called after
|
||||
// layout to copy its properties across?
|
||||
- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(RCTSparseArray *)shadowViewRegistry
|
||||
{
|
||||
NSMutableArray *uiBlocks = [NSMutableArray new];
|
||||
|
||||
// TODO: are modules global, or specific to a given rootView?
|
||||
for (RCTShadowView *rootView in shadowViewRegistry.allObjects) {
|
||||
if (![rootView isReactRootView]) {
|
||||
// This isn't a root view
|
||||
continue;
|
||||
}
|
||||
|
||||
if (![rootView isTextDirty]) {
|
||||
// No text processing to be done
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: this is a slightly weird way to do this - a recursive approach would be cleaner
|
||||
RCTSparseArray *reactTaggedAttributedStrings = [[RCTSparseArray alloc] init];
|
||||
NSMutableArray *queue = [NSMutableArray arrayWithObject:rootView];
|
||||
for (NSInteger i = 0; i < [queue count]; i++) {
|
||||
RCTShadowView *shadowView = queue[i];
|
||||
RCTAssert([shadowView isTextDirty], @"Don't process any nodes that don't have dirty text");
|
||||
|
||||
if ([shadowView isKindOfClass:[RCTShadowText class]]) {
|
||||
RCTShadowText *shadowText = (RCTShadowText *)shadowView;
|
||||
reactTaggedAttributedStrings[shadowText.reactTag] = [shadowText attributedString];
|
||||
} else if ([shadowView isKindOfClass:[RCTShadowRawText class]]) {
|
||||
RCTLogError(@"Raw text cannot be used outside of a <Text> tag. Not rendering string: '%@'", [(RCTShadowRawText *)shadowView text]);
|
||||
} else {
|
||||
for (RCTShadowView *child in [shadowView reactSubviews]) {
|
||||
if ([child isTextDirty]) {
|
||||
[queue addObject:child];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[shadowView setTextComputed];
|
||||
}
|
||||
|
||||
[uiBlocks addObject:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
[reactTaggedAttributedStrings enumerateObjectsUsingBlock:^(NSAttributedString *attributedString, NSNumber *reactTag, BOOL *stop) {
|
||||
RCTText *text = viewRegistry[reactTag];
|
||||
text.attributedText = attributedString;
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
return ^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
for (RCTViewManagerUIBlock shadowBlock in uiBlocks) {
|
||||
shadowBlock(uiManager, viewRegistry);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
195
Libraries/Text/Text.js
Normal file
195
Libraries/Text/Text.js
Normal file
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule Text
|
||||
* @typechecks static-only
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var StyleSheetPropType = require('StyleSheetPropType');
|
||||
var TextStylePropTypes = require('TextStylePropTypes');
|
||||
var Touchable = require('Touchable');
|
||||
|
||||
var createReactIOSNativeComponentClass =
|
||||
require('createReactIOSNativeComponentClass');
|
||||
var merge = require('merge');
|
||||
|
||||
var stylePropType = StyleSheetPropType(TextStylePropTypes);
|
||||
|
||||
var viewConfig = {
|
||||
validAttributes: merge(ReactIOSViewAttributes.UIView, {
|
||||
isHighlighted: true,
|
||||
numberOfLines: true,
|
||||
}),
|
||||
uiViewClassName: 'RCTText',
|
||||
};
|
||||
|
||||
/**
|
||||
* <Text> - A react component for displaying text which supports nesting,
|
||||
* styling, and touch handling. In the following example, the nested title and
|
||||
* body text will inherit the `fontFamily` from `styles.baseText`, but the title
|
||||
* provides its own additional styles. The title and body will stack on top of
|
||||
* each other on account of the literal newlines:
|
||||
*
|
||||
* renderText: function() {
|
||||
* return (
|
||||
* <Text style={styles.baseText}>
|
||||
* <Text style={styles.titleText} onPress={this._onPressTitle}>
|
||||
* {this.state.titleText + '\n\n'}
|
||||
* </Text>
|
||||
* <Text numberOfLines={5}>
|
||||
* {this.state.bodyText}
|
||||
* </Text>
|
||||
* </Text>
|
||||
* );
|
||||
* },
|
||||
* ...
|
||||
* var styles = StyleSheet.create({
|
||||
* baseText: {
|
||||
* fontFamily: 'Cochin',
|
||||
* },
|
||||
* titleText: {
|
||||
* fontSize: 20,
|
||||
* fontWeight: 'bold',
|
||||
* },
|
||||
* };
|
||||
*
|
||||
* More example code in `TextExample.ios.js`
|
||||
*/
|
||||
|
||||
var Text = React.createClass({
|
||||
|
||||
mixins: [Touchable.Mixin, NativeMethodsMixin],
|
||||
|
||||
statics: {
|
||||
stylePropType: stylePropType,
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
/**
|
||||
* Used to truncate the text with an elipsis after computing the text
|
||||
* layout, including line wrapping, such that the total number of lines does
|
||||
* not exceed this number.
|
||||
*/
|
||||
numberOfLines: React.PropTypes.number,
|
||||
/**
|
||||
* This function is called on press. Text intrinsically supports press
|
||||
* handling with a default highlight state (which can be disabled with
|
||||
* `suppressHighlighting`).
|
||||
*/
|
||||
onPress: React.PropTypes.func,
|
||||
/**
|
||||
* When true, no visual change is made when text is pressed down. By
|
||||
* default, a gray oval highlights the text on press down.
|
||||
*/
|
||||
suppressHighlighting: React.PropTypes.bool,
|
||||
style: stylePropType,
|
||||
},
|
||||
|
||||
viewConfig: viewConfig,
|
||||
|
||||
getInitialState: function() {
|
||||
return merge(this.touchableGetInitialState(), {
|
||||
isHighlighted: false,
|
||||
});
|
||||
},
|
||||
|
||||
onStartShouldSetResponder: function() {
|
||||
var shouldSetFromProps = this.props.onStartShouldSetResponder &&
|
||||
this.props.onStartShouldSetResponder();
|
||||
return shouldSetFromProps || !!this.props.onPress;
|
||||
},
|
||||
|
||||
/*
|
||||
* Returns true to allow responder termination
|
||||
*/
|
||||
handleResponderTerminationRequest: function() {
|
||||
// Allow touchable or props.onResponderTerminationRequest to deny
|
||||
// the request
|
||||
var allowTermination = this.touchableHandleResponderTerminationRequest();
|
||||
if (allowTermination && this.props.onResponderTerminationRequest) {
|
||||
allowTermination = this.props.onResponderTerminationRequest();
|
||||
}
|
||||
return allowTermination;
|
||||
},
|
||||
|
||||
handleResponderGrant: function(e, dispatchID) {
|
||||
this.touchableHandleResponderGrant(e, dispatchID);
|
||||
this.props.onResponderGrant &&
|
||||
this.props.onResponderGrant.apply(this, arguments);
|
||||
},
|
||||
|
||||
handleResponderMove: function(e) {
|
||||
this.touchableHandleResponderMove(e);
|
||||
this.props.onResponderMove &&
|
||||
this.props.onResponderMove.apply(this, arguments);
|
||||
},
|
||||
|
||||
handleResponderRelease: function(e) {
|
||||
this.touchableHandleResponderRelease(e);
|
||||
this.props.onResponderRelease &&
|
||||
this.props.onResponderRelease.apply(this, arguments);
|
||||
},
|
||||
|
||||
handleResponderTerminate: function(e) {
|
||||
this.touchableHandleResponderTerminate(e);
|
||||
this.props.onResponderTerminate &&
|
||||
this.props.onResponderTerminate.apply(this, arguments);
|
||||
},
|
||||
|
||||
touchableHandleActivePressIn: function() {
|
||||
if (this.props.suppressHighlighting || !this.props.onPress) {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
isHighlighted: true,
|
||||
});
|
||||
},
|
||||
|
||||
touchableHandleActivePressOut: function() {
|
||||
if (this.props.suppressHighlighting || !this.props.onPress) {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
isHighlighted: false,
|
||||
});
|
||||
},
|
||||
|
||||
touchableHandlePress: function() {
|
||||
this.props.onPress && this.props.onPress();
|
||||
},
|
||||
|
||||
touchableGetPressRectOffset: function() {
|
||||
return PRESS_RECT_OFFSET;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var props = {};
|
||||
for (var key in this.props) {
|
||||
props[key] = this.props[key];
|
||||
}
|
||||
props.ref = this.getNodeHandle();
|
||||
// Text is accessible by default
|
||||
if (props.accessible !== false) {
|
||||
props.accessible = true;
|
||||
}
|
||||
props.isHighlighted = this.state.isHighlighted;
|
||||
props.onStartShouldSetResponder = this.onStartShouldSetResponder;
|
||||
props.onResponderTerminationRequest =
|
||||
this.handleResponderTerminationRequest;
|
||||
props.onResponderGrant = this.handleResponderGrant;
|
||||
props.onResponderMove = this.handleResponderMove;
|
||||
props.onResponderRelease = this.handleResponderRelease;
|
||||
props.onResponderTerminate = this.handleResponderTerminate;
|
||||
return <RKText {...props} />;
|
||||
},
|
||||
});
|
||||
|
||||
var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
|
||||
|
||||
var RKText = createReactIOSNativeComponentClass(viewConfig);
|
||||
|
||||
module.exports = Text;
|
||||
46
Libraries/Text/TextStylePropTypes.js
Normal file
46
Libraries/Text/TextStylePropTypes.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule TextStylePropTypes
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var ReactPropTypes = require('ReactPropTypes');
|
||||
var ViewStylePropTypes = require('ViewStylePropTypes');
|
||||
|
||||
var merge = require('merge');
|
||||
|
||||
var TextStylePropTypes = merge(
|
||||
ViewStylePropTypes, {
|
||||
fontFamily: ReactPropTypes.string,
|
||||
fontSize: ReactPropTypes.number,
|
||||
fontWeight: ReactPropTypes.oneOf(['normal' /*default*/, 'bold']),
|
||||
fontStyle: ReactPropTypes.oneOf(['normal', 'italic']),
|
||||
lineHeight: ReactPropTypes.number,
|
||||
color: ReactPropTypes.string,
|
||||
containerBackgroundColor: ReactPropTypes.string,
|
||||
textAlign: ReactPropTypes.oneOf(
|
||||
['auto' /*default*/, 'left', 'right', 'center']
|
||||
),
|
||||
writingDirection: ReactPropTypes.oneOf(
|
||||
['auto' /*default*/, 'ltr', 'rtl']
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
// Text doesn't support padding correctly (#4841912)
|
||||
var unsupportedProps = Object.keys({
|
||||
padding: null,
|
||||
paddingTop: null,
|
||||
paddingLeft: null,
|
||||
paddingRight: null,
|
||||
paddingBottom: null,
|
||||
paddingVertical: null,
|
||||
paddingHorizontal: null,
|
||||
});
|
||||
|
||||
for (var key in unsupportedProps) {
|
||||
delete TextStylePropTypes[key];
|
||||
}
|
||||
|
||||
module.exports = TextStylePropTypes;
|
||||
Reference in New Issue
Block a user