select up and down the inspector hierarchy

Summary:
This allows you to select the displayed owner hierarchy, and see the styles,
props, and position.

@public

Test Plan:
Open the inspector, select something in the middle of the page. Click the
breadcrumb train in the inspector, and verify that:
- styles are reflected
- margin/padding/box is correct
- the highlight updates to show the selected item

See video as well.

[Video](https://www.latest.facebook.com/pxlcld/mqnl)

Screenshot
{F22518618}
This commit is contained in:
Jared Forsyth 2015-06-04 10:27:51 -07:00
parent 015b5cf8e5
commit 53b2c39cc0
3 changed files with 92 additions and 15 deletions

View File

@ -18,38 +18,79 @@ var View = require('View');
var PropTypes = require('ReactPropTypes');
var BoxInspector = require('BoxInspector');
var StyleInspector = require('StyleInspector');
var TouchableHighlight = require('TouchableHighlight');
var TouchableWithoutFeedback = require('TouchableWithoutFeedback');
var flattenStyle = require('flattenStyle');
var mapWithSeparator = require('mapWithSeparator');
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(' > ');
var selection = this.props.selection;
// Without the `TouchableWithoutFeedback`, taps on this inspector pane
// would change the inspected element to whatever is under the inspector
return (
<TouchableWithoutFeedback>
<View style={styles.info}>
<Text style={styles.path}>
{path}
<View style={styles.breadcrumb}>
{mapWithSeparator(
this.props.hierarchy,
(item, i) => (
<TouchableHighlight
style={[styles.breadItem, i === selection && styles.selected]}
onPress={() => this.props.setSelection(i)}>
<Text style={styles.breadItemText}>
{item.getName ? item.getName() : 'Unknown'}
</Text>
</TouchableHighlight>
),
() => <Text style={styles.breadSep}>&#9656;</Text>
)}
</View>
<View style={styles.row}>
<StyleInspector style={style} />
<BoxInspector style={style} frame={this.props.frame} />
</View>
</View>
</TouchableWithoutFeedback>
);
}
});
var styles = StyleSheet.create({
breadSep: {
fontSize: 8,
color: 'white',
},
breadcrumb: {
flexDirection: 'row',
flexWrap: 'wrap',
marginBottom: 5,
},
selected: {
borderColor: 'white',
borderRadius: 5,
},
breadItem: {
borderWidth: 1,
borderColor: 'transparent',
marginHorizontal: 2,
},
breadItemText: {
fontSize: 10,
color: 'white',
marginHorizontal: 5,
},
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-around',
justifyContent: 'space-between',
},
info: {
backgroundColor: 'rgba(0, 0, 0, 0.7)',

View File

@ -24,7 +24,9 @@ var InspectorOverlay = React.createClass({
getInitialState: function() {
return {
frame: null,
pointerY: 0,
hierarchy: [],
selection: -1,
};
},
@ -42,6 +44,8 @@ var InspectorOverlay = React.createClass({
var publicInstance = instance.getPublicInstance();
this.setState({
hierarchy,
pointerY: locationY,
selection: hierarchy.length - 1,
frame: {left, top, width, height},
style: publicInstance.props ? publicInstance.props.style : {},
});
@ -49,6 +53,18 @@ var InspectorOverlay = React.createClass({
);
},
setSelection(i) {
var instance = this.state.hierarchy[i];
var publicInstance = instance.getPublicInstance();
UIManager.measure(React.findNodeHandle(instance), (x, y, width, height, left, top) => {
this.setState({
frame: {left, top, width, height},
style: publicInstance.props ? publicInstance.props.style : {},
selection: i,
});
});
},
shouldSetResponser: function(e) {
this.findViewForTouchEvent(e);
return true;
@ -59,9 +75,8 @@ var InspectorOverlay = React.createClass({
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 distanceToTop = this.state.pointerY;
var distanceToBottom = Dimensions.get('window').height - distanceToTop;
justifyContent = distanceToTop > distanceToBottom
? 'flex-start'
@ -73,6 +88,8 @@ var InspectorOverlay = React.createClass({
style={this.state.style}
frame={this.state.frame}
hierarchy={this.state.hierarchy}
selection={this.state.selection}
setSelection={this.setSelection}
/>
);
} else {

View File

@ -0,0 +1,19 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule mapWithSeparator
*/
'use strict';
function mapWithSeparator(array, valueFunction, separatorFunction) {
var results = [];
for (var i = 0; i < array.length; i++) {
results.push(valueFunction(array[i], i, array));
if (i !== array.length - 1) {
results.push(separatorFunction(i));
}
}
return results;
}
module.exports = mapWithSeparator;