mirror of
https://github.com/status-im/react-native.git
synced 2025-01-13 19:15:05 +00:00
[ReactNative] introduce requireNativeComponent
This commit is contained in:
parent
baed197a7d
commit
764854c04a
37
Libraries/Components/UnimplementedViews/UnimplementedView.js
Normal file
37
Libraries/Components/UnimplementedViews/UnimplementedView.js
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Common implementation for a simple stubbed view. Simply applies the view's styles to the inner
|
||||
* View component and renders its children.
|
||||
*
|
||||
* @providesModule UnimplementedView
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var View = require('View');
|
||||
|
||||
var UnimplementedView = React.createClass({
|
||||
setNativeProps: function() {
|
||||
// Do nothing.
|
||||
// This method is required in order to use this view as a Touchable* child.
|
||||
// See ensureComponentIsNative.js for more info
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<View style={[styles.unimplementedView, this.props.style]}>
|
||||
{this.props.children}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
unimplementedView: {
|
||||
borderWidth: 1,
|
||||
borderColor: 'red',
|
||||
alignSelf: 'flex-start',
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = UnimplementedView;
|
62
Libraries/ReactIOS/requireNativeComponent.js
Normal file
62
Libraries/ReactIOS/requireNativeComponent.js
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule requireNativeComponent
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RCTUIManager = require('NativeModules').UIManager;
|
||||
var UnimplementedView = require('UnimplementedView');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
var deepDiffer = require('deepDiffer');
|
||||
var insetsDiffer = require('insetsDiffer');
|
||||
var pointsDiffer = require('pointsDiffer');
|
||||
var matricesDiffer = require('matricesDiffer');
|
||||
var sizesDiffer = require('sizesDiffer');
|
||||
|
||||
/**
|
||||
* Used to create React components that directly wrap native component
|
||||
* implementations. Config information is extracted from data exported from the
|
||||
* RCTUIManager module. It is still strongly preferred that you wrap the native
|
||||
* component in a hand-written component with full propTypes definitions and
|
||||
* other documentation.
|
||||
*
|
||||
* Common types are lined up with the appropriate prop differs with
|
||||
* `TypeToDifferMap`. Non-scalar types not in the map default to `deepDiffer`.
|
||||
*/
|
||||
function requireNativeComponent(viewName: string): Function {
|
||||
var viewConfig = RCTUIManager.viewConfigs && RCTUIManager.viewConfigs[viewName];
|
||||
if (!viewConfig) {
|
||||
return UnimplementedView;
|
||||
}
|
||||
var nativeProps = {
|
||||
...RCTUIManager.viewConfigs.RCTView.nativeProps,
|
||||
...viewConfig.nativeProps,
|
||||
};
|
||||
viewConfig.validAttributes = {};
|
||||
for (var key in nativeProps) {
|
||||
// TODO: deep diff by default in diffRawProperties instead of setting it here
|
||||
var differ = TypeToDifferMap[nativeProps[key].type] || deepDiffer;
|
||||
viewConfig.validAttributes[key] = {diff: differ};
|
||||
}
|
||||
return createReactIOSNativeComponentClass(viewConfig);
|
||||
}
|
||||
|
||||
var TypeToDifferMap = {
|
||||
// iOS Types
|
||||
CATransform3D: matricesDiffer,
|
||||
CGPoint: pointsDiffer,
|
||||
CGSize: sizesDiffer,
|
||||
UIEdgeInsets: insetsDiffer,
|
||||
// Android Types
|
||||
// (not yet implemented)
|
||||
};
|
||||
|
||||
module.exports = requireNativeComponent;
|
19
Libraries/Utilities/differ/sizesDiffer.js
Normal file
19
Libraries/Utilities/differ/sizesDiffer.js
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule sizesDiffer
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var dummySize = {w: undefined, h: undefined};
|
||||
|
||||
var sizesDiffer = function(one, two) {
|
||||
one = one || dummySize;
|
||||
two = two || dummySize;
|
||||
return one !== two && (
|
||||
one.w !== two.w ||
|
||||
one.h !== two.h
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = sizesDiffer;
|
1
Libraries/react-native/react-native.js
vendored
1
Libraries/react-native/react-native.js
vendored
@ -59,6 +59,7 @@ var ReactNative = Object.assign(Object.create(require('React')), {
|
||||
// Plugins
|
||||
DeviceEventEmitter: require('RCTDeviceEventEmitter'),
|
||||
NativeModules: require('NativeModules'),
|
||||
requireNativeComponent: require('requireNativeComponent'),
|
||||
|
||||
addons: {
|
||||
LinkedStateMixin: require('LinkedStateMixin'),
|
||||
|
@ -193,6 +193,7 @@ static UIViewAnimationCurve UIViewAnimationCurveFromRCTAnimationType(RCTAnimatio
|
||||
NSMutableDictionary *_defaultShadowViews; // RCT thread only
|
||||
NSMutableDictionary *_defaultViews; // Main thread only
|
||||
NSDictionary *_viewManagers;
|
||||
NSDictionary *_viewConfigs;
|
||||
NSUInteger _rootTag;
|
||||
}
|
||||
|
||||
@ -219,6 +220,28 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
|
||||
return name;
|
||||
}
|
||||
|
||||
static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewName)
|
||||
{
|
||||
NSMutableDictionary *nativeProps = [[NSMutableDictionary alloc] init];
|
||||
static const char *prefix = "getPropConfig";
|
||||
static const NSUInteger prefixLength = sizeof("getPropConfig") - 1;
|
||||
unsigned int methodCount = 0;
|
||||
Method *methods = class_copyMethodList(objc_getMetaClass(class_getName(managerClass)), &methodCount);
|
||||
for (unsigned int i = 0; i < methodCount; i++) {
|
||||
Method method = methods[i];
|
||||
SEL getInfo = method_getName(method);
|
||||
const char *selName = sel_getName(getInfo);
|
||||
if (strlen(selName) > prefixLength && strncmp(selName, prefix, prefixLength) == 0) {
|
||||
NSDictionary *info = ((NSDictionary *(*)(id, SEL))method_getImplementation(method))(managerClass, getInfo);
|
||||
nativeProps[info[@"name"]] = info;
|
||||
}
|
||||
}
|
||||
return @{
|
||||
@"uiViewClassName": viewName,
|
||||
@"nativeProps": nativeProps
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This private constructor should only be called when creating
|
||||
* isolated UIImanager instances for testing. Normal initialization
|
||||
@ -292,13 +315,17 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName)
|
||||
|
||||
// Get view managers from bridge
|
||||
NSMutableDictionary *viewManagers = [[NSMutableDictionary alloc] init];
|
||||
NSMutableDictionary *viewConfigs = [[NSMutableDictionary alloc] init];
|
||||
[_bridge.modules enumerateKeysAndObjectsUsingBlock:^(NSString *moduleName, RCTViewManager *manager, BOOL *stop) {
|
||||
if ([manager isKindOfClass:[RCTViewManager class]]) {
|
||||
viewManagers[RCTViewNameForModuleName(moduleName)] = manager;
|
||||
NSString *viewName = RCTViewNameForModuleName(moduleName);
|
||||
viewManagers[viewName] = manager;
|
||||
viewConfigs[viewName] = RCTViewConfigForModule([manager class], viewName);
|
||||
}
|
||||
}];
|
||||
|
||||
_viewManagers = [viewManagers copy];
|
||||
_viewConfigs = [viewConfigs copy];
|
||||
}
|
||||
|
||||
- (void)registerRootView:(UIView *)rootView;
|
||||
@ -1374,7 +1401,7 @@ RCT_EXPORT_METHOD(clearJSResponder)
|
||||
allJSConstants[name] = [constantsNamespace copy];
|
||||
}
|
||||
}];
|
||||
|
||||
allJSConstants[@"viewConfigs"] = _viewConfigs;
|
||||
return allJSConstants;
|
||||
}
|
||||
|
||||
|
@ -109,6 +109,7 @@ typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *v
|
||||
* within the view or shadowView.
|
||||
*/
|
||||
#define RCT_REMAP_VIEW_PROPERTY(name, keyPath, type) \
|
||||
RCT_EXPORT_VIEW_PROP_CONFIG(name, type) \
|
||||
- (void)set_##name:(id)json forView:(id)view withDefaultView:(id)defaultView { \
|
||||
if ((json && !RCTSetProperty(view, @#keyPath, @selector(type:), json)) || \
|
||||
(!json && !RCTCopyProperty(view, defaultView, @#keyPath))) { \
|
||||
@ -117,6 +118,7 @@ typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *v
|
||||
}
|
||||
|
||||
#define RCT_REMAP_SHADOW_PROPERTY(name, keyPath, type) \
|
||||
RCT_EXPORT_SHADOW_PROP_CONFIG(name, type) \
|
||||
- (void)set_##name:(id)json forShadowView:(id)view withDefaultView:(id)defaultView { \
|
||||
if ((json && !RCTSetProperty(view, @#keyPath, @selector(type:), json)) || \
|
||||
(!json && !RCTCopyProperty(view, defaultView, @#keyPath))) { \
|
||||
@ -130,9 +132,11 @@ typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *v
|
||||
* refer to "json", "view" and "defaultView" to implement the required logic.
|
||||
*/
|
||||
#define RCT_CUSTOM_VIEW_PROPERTY(name, type, viewClass) \
|
||||
RCT_EXPORT_VIEW_PROP_CONFIG(name, type) \
|
||||
- (void)set_##name:(id)json forView:(viewClass *)view withDefaultView:(viewClass *)defaultView
|
||||
|
||||
#define RCT_CUSTOM_SHADOW_PROPERTY(name, type, viewClass) \
|
||||
RCT_EXPORT_SHADOW_PROP_CONFIG(name, type) \
|
||||
- (void)set_##name:(id)json forShadowView:(viewClass *)view withDefaultView:(viewClass *)defaultView
|
||||
|
||||
/**
|
||||
@ -160,4 +164,17 @@ typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *v
|
||||
[self set_##newName:json forView:view withDefaultView:defaultView]; \
|
||||
}
|
||||
|
||||
/**
|
||||
* PROP_CONFIG macros should only be paired with property setters.
|
||||
*/
|
||||
#define RCT_EXPORT_VIEW_PROP_CONFIG(name, type) \
|
||||
+ (NSDictionary *)getPropConfigView_##name { \
|
||||
return @{@"name": @#name, @"type": @#type}; \
|
||||
}
|
||||
|
||||
#define RCT_EXPORT_SHADOW_PROP_CONFIG(name, type) \
|
||||
+ (NSDictionary *)getPropConfigShadow_##name { \
|
||||
return @{@"name": @#name, @"type": @#type}; \
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
x
Reference in New Issue
Block a user