/**
* Copyright (c) Nicolas Gallagher.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import applyLayout from '../../modules/applyLayout';
import applyNativeMethods from '../../modules/applyNativeMethods';
import { bool } from 'prop-types';
import createElement from '../createElement';
import css from '../StyleSheet/css';
import filterSupportedProps from './filterSupportedProps';
import invariant from 'fbjs/lib/invariant';
import warning from 'fbjs/lib/warning';
import StyleSheet from '../StyleSheet';
import ViewPropTypes, { type ViewProps } from './ViewPropTypes';
import React, { Component } from 'react';
const calculateHitSlopStyle = hitSlop => {
const hitStyle = {};
for (const prop in hitSlop) {
if (hitSlop.hasOwnProperty(prop)) {
const value = hitSlop[prop];
hitStyle[prop] = value > 0 ? -1 * value : 0;
}
}
return hitStyle;
};
class View extends Component<ViewProps> {
static displayName = 'View';
static contextTypes = {
isInAParentText: bool
};
static propTypes = ViewPropTypes;
render() {
const hitSlop = this.props.hitSlop;
const supportedProps = filterSupportedProps(this.props);
if (process.env.NODE_ENV !== 'production') {
warning(this.props.className == null, 'Using the "className" prop on <View> is deprecated.');
React.Children.toArray(this.props.children).forEach(item => {
invariant(
typeof item !== 'string',
`Unexpected text node: ${item}. A text node cannot be a child of a <View>.`
);
});
}
const { isInAParentText } = this.context;
supportedProps.classList = [this.props.className, classes.view];
supportedProps.style = StyleSheet.compose(
isInAParentText && styles.inline,
this.props.style
);
if (hitSlop) {
const hitSlopStyle = calculateHitSlopStyle(hitSlop);
const hitSlopChild = createElement('span', {
classList: [classes.hitSlop],
style: hitSlopStyle
});
supportedProps.children = React.Children.toArray([hitSlopChild, supportedProps.children]);
}
return createElement('div', supportedProps);
}
}
const classes = css.create({
view: {
alignItems: 'stretch',
border: '0 solid black',
boxSizing: 'border-box',
display: 'flex',
flexBasis: 'auto',
flexDirection: 'column',
flexShrink: 0,
margin: 0,
minHeight: 0,
minWidth: 0,
padding: 0,
position: 'relative',
zIndex: 0
},
// this zIndex-ordering positions the hitSlop above the View but behind
// its children
hitSlop: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: -1
}
});
const styles = StyleSheet.create({
inline: {
display: 'inline-flex'
}
});
export default applyLayout(applyNativeMethods(View));