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