1/** 2 * Copyright (c) Expo. 3 * Copyright (c) Nicolas Gallagher. 4 * Copyright (c) Facebook, Inc. and its affiliates. 5 * 6 * This source code is licensed under the MIT license found in the 7 * LICENSE file in the root directory of this source tree. 8 */ 9import * as React from 'react'; 10import StyleSheet from 'react-native-web/dist/exports/StyleSheet'; 11import css from 'react-native-web/dist/exports/StyleSheet/css'; 12import TextAncestorContext from 'react-native-web/dist/exports/Text/TextAncestorContext'; 13import createElement from 'react-native-web/dist/exports/createElement'; 14import * as forwardedProps from 'react-native-web/dist/modules/forwardedProps'; 15import pick from 'react-native-web/dist/modules/pick'; 16import useElementLayout from 'react-native-web/dist/modules/useElementLayout'; 17import useMergeRefs from 'react-native-web/dist/modules/useMergeRefs'; 18import usePlatformMethods from 'react-native-web/dist/modules/usePlatformMethods'; 19import useResponderEvents from 'react-native-web/dist/modules/useResponderEvents'; 20import { PlatformMethods, ViewProps } from 'react-native-web/dist/types'; 21 22const forwardPropsList = { 23 ...forwardedProps.defaultProps, 24 ...forwardedProps.accessibilityProps, 25 ...forwardedProps.clickProps, 26 ...forwardedProps.focusProps, 27 ...forwardedProps.keyboardProps, 28 ...forwardedProps.mouseProps, 29 ...forwardedProps.touchProps, 30 ...forwardedProps.styleProps, 31 lang: true, 32 onScroll: true, 33 onWheel: true, 34 pointerEvents: true, 35}; 36 37const pickProps = (props) => pick(props, forwardPropsList); 38 39/** 40 * This is the View from react-native-web copied out in order to supply a custom `__element` property. 41 * In the past, you could use `createElement` to create an element with a custom HTML element, but this changed 42 * somewhere between 0.14...0.17. 43 */ 44 45// @ts-ignore 46const View: React.AbstractComponent<ViewProps, HTMLElement & PlatformMethods> = React.forwardRef( 47 (props, forwardedRef) => { 48 const { 49 onLayout, 50 onMoveShouldSetResponder, 51 onMoveShouldSetResponderCapture, 52 onResponderEnd, 53 onResponderGrant, 54 onResponderMove, 55 onResponderReject, 56 onResponderRelease, 57 onResponderStart, 58 onResponderTerminate, 59 onResponderTerminationRequest, 60 onScrollShouldSetResponder, 61 onScrollShouldSetResponderCapture, 62 onSelectionChangeShouldSetResponder, 63 onSelectionChangeShouldSetResponderCapture, 64 onStartShouldSetResponder, 65 onStartShouldSetResponderCapture, 66 __element, 67 } = props as any; 68 69 const hasTextAncestor = React.useContext(TextAncestorContext); 70 const hostRef = React.useRef(null); 71 72 useElementLayout(hostRef, onLayout); 73 useResponderEvents(hostRef, { 74 onMoveShouldSetResponder, 75 onMoveShouldSetResponderCapture, 76 onResponderEnd, 77 onResponderGrant, 78 onResponderMove, 79 onResponderReject, 80 onResponderRelease, 81 onResponderStart, 82 onResponderTerminate, 83 onResponderTerminationRequest, 84 onScrollShouldSetResponder, 85 onScrollShouldSetResponderCapture, 86 onSelectionChangeShouldSetResponder, 87 onSelectionChangeShouldSetResponderCapture, 88 onStartShouldSetResponder, 89 onStartShouldSetResponderCapture, 90 }); 91 92 const style = StyleSheet.compose( 93 hasTextAncestor && styles.inline, 94 // @ts-ignore: untyped 95 props.style 96 ); 97 98 const supportedProps = pickProps(props); 99 supportedProps.classList = classList; 100 supportedProps.style = style; 101 102 const platformMethodsRef = usePlatformMethods(supportedProps); 103 const setRef = useMergeRefs(hostRef, platformMethodsRef, forwardedRef); 104 105 supportedProps.ref = setRef; 106 107 return createElement(__element, supportedProps); 108 } 109); 110 111View.displayName = 'View'; 112 113const classes = css.create({ 114 view: { 115 alignItems: 'stretch', 116 border: '0 solid black', 117 boxSizing: 'border-box', 118 display: 'flex', 119 flexBasis: 'auto', 120 flexDirection: 'column', 121 flexShrink: 0, 122 margin: 0, 123 minHeight: 0, 124 minWidth: 0, 125 padding: 0, 126 position: 'relative', 127 zIndex: 0, 128 }, 129}); 130 131const classList = [classes.view]; 132 133const styles = StyleSheet.create({ 134 inline: { 135 display: 'inline-flex', 136 }, 137}); 138 139export default View; 140