add style inspector + more margin + styles

Summary:
- make overlay transparent to avoid obscuring the app
- show style in the inspector pane
- show margin+padding values, also width/height and abs position

@public

Test Plan:
Open the inspector somewhere, start selecting things. You should see correct
padding, margin, and dimentions values; in addition to all style properties
enumerated.
This commit is contained in:
Jared Forsyth
2015-06-03 13:55:52 -07:00
parent 074fa759a6
commit b2b89c0b68
7 changed files with 277 additions and 34 deletions

View File

@@ -50,6 +50,9 @@ function findInstanceByNativeTag(rootTag, nativeTag) {
var containerID = ReactNativeTagHandles.tagToRootNodeID[rootTag];
var rootInstance = ReactNativeMount._instancesByContainerID[containerID];
var targetID = ReactNativeTagHandles.tagToRootNodeID[nativeTag];
if (!targetID) {
return undefined;
}
return findInstance(rootInstance, targetID);
}

View File

@@ -0,0 +1,113 @@
/**
* 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 BoxInspector
* @flow
*/
'use strict';
var React = require('React');
var StyleSheet = require('StyleSheet');
var Text = require('Text');
var View = require('View');
var resolveBoxStyle = require('resolveBoxStyle');
var blank = {
top: 0,
left: 0,
right: 0,
bottom: 0,
};
class BoxInspector extends React.Component {
render() {
var frame = this.props.frame;
var style = this.props.style;
var margin = style && resolveBoxStyle('margin', style) || blank;
var padding = style && resolveBoxStyle('padding', style) || blank;
return (
<BoxContainer title="margin" titleStyle={styles.marginLabel} box={margin}>
<BoxContainer title="padding" box={padding}>
<View>
<Text style={styles.innerText}>
({frame.left}, {frame.top})
</Text>
<Text style={styles.innerText}>
{frame.width} &times; {frame.height}
</Text>
</View>
</BoxContainer>
</BoxContainer>
);
}
}
class BoxContainer extends React.Component {
render() {
var box = this.props.box;
return (
<View style={styles.box}>
<View style={styles.row}>
<Text style={[this.props.titleStyle, styles.label]}>{this.props.title}</Text>
<Text style={styles.boxText}>{box.top}</Text>
</View>
<View style={styles.row}>
<Text style={styles.boxText}>{box.left}</Text>
{this.props.children}
<Text style={styles.boxText}>{box.right}</Text>
</View>
<Text style={styles.boxText}>{box.bottom}</Text>
</View>
);
}
}
var styles = StyleSheet.create({
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-around',
},
marginLabel: {
width: 60,
},
label: {
fontSize: 10,
color: 'rgb(255,100,0)',
marginLeft: 5,
flex: 1,
textAlign: 'left',
top: -3,
},
buffer: {
fontSize: 10,
color: 'yellow',
flex: 1,
textAlign: 'center',
},
innerText: {
color: 'yellow',
fontSize: 12,
textAlign: 'center',
width: 70,
},
box: {
borderWidth: 1,
borderColor: 'grey',
},
boxText: {
color: 'white',
fontSize: 12,
marginHorizontal: 3,
marginVertical: 2,
textAlign: 'center',
},
});
module.exports = BoxInspector;

View File

@@ -60,13 +60,13 @@ var styles = StyleSheet.create({
position: 'absolute',
},
content: {
backgroundColor: 'rgba(0, 0, 255, 0.1)',
backgroundColor: 'rgba(200, 230, 255, 0.8)',
},
padding: {
borderColor: 'rgba(182, 217, 167, 0.3)',
borderColor: 'rgba(77, 255, 0, 0.3)',
},
margin: {
borderColor: 'rgba(248, 194, 136, 0.3)',
borderColor: 'rgba(255, 132, 0, 0.3)',
},
});

View File

@@ -0,0 +1,64 @@
/**
* 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 ElementProperties
* @flow
*/
'use strict';
var React = require('React');
var StyleSheet = require('StyleSheet');
var Text = require('Text');
var View = require('View');
var PropTypes = require('ReactPropTypes');
var BoxInspector = require('BoxInspector');
var StyleInspector = require('StyleInspector');
var flattenStyle = require('flattenStyle');
var ElementProperties = React.createClass({
propTypes: {
hierarchy: PropTypes.array.isRequired,
style: PropTypes.array.isRequired,
},
render: function() {
var style = flattenStyle(this.props.style);
var path = this.props.hierarchy.map((instance) => {
return instance.getName ? instance.getName() : 'Unknown';
}).join(' > ');
return (
<View style={styles.info}>
<Text style={styles.path}>
{path}
</Text>
<View style={styles.row}>
<StyleInspector style={style} />
<BoxInspector style={style} frame={this.props.frame} />
</View>
</View>
);
}
});
var styles = StyleSheet.create({
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-around',
},
info: {
backgroundColor: 'rgba(0, 0, 0, 0.7)',
padding: 10,
},
path: {
color: 'white',
fontSize: 9,
},
});
module.exports = ElementProperties;

View File

@@ -18,6 +18,7 @@ var Text = require('Text');
var UIManager = require('NativeModules').UIManager;
var View = require('View');
var ElementBox = require('ElementBox');
var ElementProperties = require('ElementProperties');
var InspectorOverlay = React.createClass({
getInitialState: function() {
@@ -34,6 +35,9 @@ var InspectorOverlay = React.createClass({
[locationX, locationY],
(nativeViewTag, left, top, width, height) => {
var instance = Inspector.findInstanceByNativeTag(this.props.rootTag, nativeViewTag);
if (!instance) {
return;
}
var hierarchy = Inspector.getOwnerHierarchy(instance);
var publicInstance = instance.getPublicInstance();
this.setState({
@@ -52,18 +56,31 @@ var InspectorOverlay = React.createClass({
render: function() {
var content = [];
var justifyContent = 'flex-end';
if (this.state.frame) {
var distanceToTop = this.state.frame.top;
var distanceToBottom = Dimensions.get('window').height -
(this.state.frame.top + this.state.frame.height);
var justifyContent = distanceToTop > distanceToBottom
justifyContent = distanceToTop > distanceToBottom
? 'flex-start'
: 'flex-end';
content.push(<ElementBox frame={this.state.frame} style={this.state.style} />);
content.push(<ElementProperties hierarchy={this.state.hierarchy} />);
content.push(
<ElementProperties
style={this.state.style}
frame={this.state.frame}
hierarchy={this.state.hierarchy}
/>
);
} else {
content.push(
<View style={styles.welcomeMessage}>
<Text style={styles.welcomeText}>Welcome to the inspector! Tap something to inspect it.</Text>
</View>
);
}
return (
<View
@@ -76,38 +93,23 @@ var InspectorOverlay = React.createClass({
}
});
var ElementProperties = React.createClass({
render: function() {
var path = this.props.hierarchy.map((instance) => {
return instance.getName ? instance.getName() : 'Unknown';
}).join(' > ');
return (
<View style={styles.info}>
<Text style={styles.path}>
{path}
</Text>
</View>
);
}
});
var styles = StyleSheet.create({
welcomeMessage: {
backgroundColor: 'rgba(0, 0, 0, 0.7)',
padding: 10,
paddingVertical: 50,
},
welcomeText: {
color: 'white',
},
inspector: {
backgroundColor: 'rgba(255,255,255,0.8)',
backgroundColor: 'rgba(255,255,255,0.0)',
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
},
info: {
backgroundColor: 'rgba(0, 0, 0, 0.7)',
padding: 10,
},
path: {
color: 'white',
fontSize: 9,
}
});
module.exports = InspectorOverlay;

View File

@@ -0,0 +1,63 @@
/**
* 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 StyleInspector
* @flow
*/
'use strict';
var React = require('React');
var StyleSheet = require('StyleSheet');
var Text = require('Text');
var View = require('View');
class StyleInspector extends React.Component {
render() {
if (!this.props.style) {
return <Text style={styles.noStyle}>No style</Text>;
}
var names = Object.keys(this.props.style);
return (
<View style={styles.container}>
<View>
{names.map(name => <Text style={styles.attr}>{name}:</Text>)}
</View>
<View>
{names.map(name => <Text style={styles.value}>{this.props.style[name]}</Text>)}
</View>
</View>
);
}
}
var styles = StyleSheet.create({
container: {
flexDirection: 'row',
},
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-around',
},
attr: {
fontSize: 10,
color: '#ccc',
},
value: {
fontSize: 10,
color: 'white',
marginLeft: 10,
},
noStyle: {
color: 'white',
fontSize: 10,
},
});
module.exports = StyleInspector;

View File

@@ -24,10 +24,10 @@ function resolveBoxStyle(prefix: String, style: Object): ?Object {
var res = {};
var subs = ['top', 'left', 'bottom', 'right'];
var set = false;
subs.forEach(sub => {
res[sub] = style[prefix] || 0;
});
if (style[prefix]) {
subs.forEach(sub => {
res[sub] = style[prefix];
});
set = true;
}
if (style[prefix + 'Vertical']) {
@@ -42,8 +42,6 @@ function resolveBoxStyle(prefix: String, style: Object): ?Object {
var val = style[prefix + capFirst(sub)];
if (val) {
res[sub] = val;
}
if (res[sub]) {
set = true;
}
});