@@ -33,7 +33,7 @@ import {
3333 isEnabled as ReactBrowserEventEmitterIsEnabled ,
3434 setEnabled as ReactBrowserEventEmitterSetEnabled ,
3535} from '../events/ReactBrowserEventEmitter' ;
36- import { getChildNamespace } from '../shared/DOMNamespaces' ;
36+ import { Namespaces , getChildNamespace } from '../shared/DOMNamespaces' ;
3737import {
3838 ELEMENT_NODE ,
3939 TEXT_NODE ,
@@ -46,6 +46,7 @@ import dangerousStyleValue from '../shared/dangerousStyleValue';
4646import type { DOMContainer } from './ReactDOM' ;
4747import type { ReactEventResponder } from 'shared/ReactTypes' ;
4848import { REACT_EVENT_TARGET_TOUCH_HIT } from 'shared/ReactSymbols' ;
49+ import { canUseDOM } from 'shared/ExecutionEnvironment' ;
4950
5051export type Type = string ;
5152export type Props = {
@@ -57,6 +58,23 @@ export type Props = {
5758 style ?: {
5859 display ?: string ,
5960 } ,
61+ bottom ?: null | number ,
62+ left ?: null | number ,
63+ right ?: null | number ,
64+ top ?: null | number ,
65+ } ;
66+ export type EventTargetChildElement = {
67+ type : string ,
68+ props : null | {
69+ style ?: {
70+ position ?: string ,
71+ zIndex ?: number ,
72+ bottom ?: string ,
73+ left ?: string ,
74+ right ?: string ,
75+ top ?: string ,
76+ } ,
77+ } ,
6078} ;
6179export type Container = Element | Document ;
6280export type Instance = Element ;
@@ -70,7 +88,6 @@ type HostContextDev = {
7088 eventData : null | { |
7189 isEventComponent ? : boolean ,
7290 isEventTarget ?: boolean ,
73- eventTargetType ?: null | Symbol | number ,
7491 | } ,
7592} ;
7693type HostContextProd = string ;
@@ -86,6 +103,8 @@ import {
86103} from 'shared/ReactFeatureFlags' ;
87104import warning from 'shared/warning' ;
88105
106+ const { html : HTML_NAMESPACE } = Namespaces ;
107+
89108// Intentionally not named imports because Rollup would
90109// use dynamic dispatch for CommonJS interop named imports.
91110const {
@@ -190,7 +209,6 @@ export function getChildHostContextForEventComponent(
190209 const eventData = {
191210 isEventComponent : true ,
192211 isEventTarget : false ,
193- eventTargetType : null ,
194212 } ;
195213 return { namespace, ancestorInfo, eventData} ;
196214 }
@@ -204,17 +222,24 @@ export function getChildHostContextForEventTarget(
204222 if ( __DEV__ ) {
205223 const parentHostContextDev = ( ( parentHostContext : any ) : HostContextDev ) ;
206224 const { namespace, ancestorInfo} = parentHostContextDev ;
207- warning (
208- parentHostContextDev . eventData === null ||
209- ! parentHostContextDev . eventData . isEventComponent ||
210- type !== REACT_EVENT_TARGET_TOUCH_HIT ,
211- 'validateDOMNesting: <TouchHitTarget> cannot not be a direct child of an event component. ' +
212- 'Ensure <TouchHitTarget> is a direct child of a DOM element.' ,
213- ) ;
225+ if ( type === REACT_EVENT_TARGET_TOUCH_HIT ) {
226+ warning (
227+ parentHostContextDev . eventData === null ||
228+ ! parentHostContextDev . eventData . isEventComponent ,
229+ 'validateDOMNesting: <TouchHitTarget> cannot not be a direct child of an event component. ' +
230+ 'Ensure <TouchHitTarget> is a direct child of a DOM element.' ,
231+ ) ;
232+ const parentNamespace = parentHostContextDev . namespace ;
233+ if ( parentNamespace !== HTML_NAMESPACE ) {
234+ throw new Error (
235+ '<TouchHitTarget> was used in an unsupported DOM namespace. ' +
236+ 'Ensure the <TouchHitTarget> is used in an HTML namespace.' ,
237+ ) ;
238+ }
239+ }
214240 const eventData = {
215241 isEventComponent : false ,
216242 isEventTarget : true ,
217- eventTargetType : type ,
218243 } ;
219244 return { namespace, ancestorInfo, eventData} ;
220245 }
@@ -249,16 +274,6 @@ export function createInstance(
249274 if ( __DEV__ ) {
250275 // TODO: take namespace into account when validating.
251276 const hostContextDev = ( ( hostContext : any ) : HostContextDev ) ;
252- if ( enableEventAPI ) {
253- const eventData = hostContextDev . eventData ;
254- if ( eventData !== null ) {
255- warning (
256- ! eventData . isEventTarget ||
257- eventData . eventTargetType !== REACT_EVENT_TARGET_TOUCH_HIT ,
258- 'Warning: validateDOMNesting: <TouchHitTarget> must not have any children.' ,
259- ) ;
260- }
261- }
262277 validateDOMNesting ( type , null , hostContextDev . ancestorInfo ) ;
263278 if (
264279 typeof props . children === 'string' ||
@@ -365,25 +380,12 @@ export function createTextInstance(
365380 if ( enableEventAPI ) {
366381 const eventData = hostContextDev . eventData ;
367382 if ( eventData !== null ) {
368- warning (
369- eventData === null ||
370- ! eventData . isEventTarget ||
371- eventData . eventTargetType !== REACT_EVENT_TARGET_TOUCH_HIT ,
372- 'Warning: validateDOMNesting: <TouchHitTarget> must not have any children.' ,
373- ) ;
374383 warning (
375384 ! eventData . isEventComponent ,
376385 'validateDOMNesting: React event components cannot have text DOM nodes as children. ' +
377386 'Wrap the child text "%s" in an element.' ,
378387 text ,
379388 ) ;
380- warning (
381- ! eventData . isEventTarget ||
382- eventData . eventTargetType === REACT_EVENT_TARGET_TOUCH_HIT ,
383- 'validateDOMNesting: React event targets cannot have text DOM nodes as children. ' +
384- 'Wrap the child text "%s" in an element.' ,
385- text ,
386- ) ;
387389 }
388390 }
389391 }
@@ -899,16 +901,74 @@ export function handleEventComponent(
899901 }
900902}
901903
904+ export function getEventTargetChildElement (
905+ type : Symbol | number ,
906+ props : Props ,
907+ ) : null | EventTargetChildElement {
908+ if ( enableEventAPI ) {
909+ if ( type === REACT_EVENT_TARGET_TOUCH_HIT ) {
910+ const { bottom , left , right , top } = props ;
911+
912+ if ( ! bottom && ! left && ! right && ! top ) {
913+ return null ;
914+ }
915+ return {
916+ type : 'div ',
917+ props : {
918+ style : {
919+ position : 'absolute ',
920+ zIndex : - 1 ,
921+ bottom : bottom ? `- $ { bottom } px ` : '0 px ',
922+ left : left ? `- $ { left } px ` : '0 px ',
923+ right : right ? `- $ { right } px ` : '0 px ',
924+ top : top ? `- $ { top } px ` : '0 px ',
925+ } ,
926+ } ,
927+ } ;
928+ }
929+ }
930+ return null ;
931+ }
932+
902933export function handleEventTarget (
903934 type : Symbol | number ,
904935 props : Props ,
905- parentInstance : Container ,
936+ rootContainerInstance : Container ,
906937 internalInstanceHandle : Object ,
938+ ) : boolean {
939+ return false ;
940+ }
941+
942+ export function commitEventTarget (
943+ type : Symbol | number ,
944+ props : Props ,
945+ instance : Instance ,
946+ parentInstance : Instance ,
907947) : void {
908948 if ( enableEventAPI ) {
909- // Touch target hit slop handling
910949 if ( type === REACT_EVENT_TARGET_TOUCH_HIT ) {
911- // TODO
950+ if ( __DEV__ && canUseDOM ) {
951+ // This is done at DEV time because getComputedStyle will
952+ // typically force a style recalculation and force a layout,
953+ // reflow -– both of which are sync are expensive.
954+ const computedStyles = window . getComputedStyle ( parentInstance ) ;
955+ const position = computedStyles . getPropertyValue ( 'position' ) ;
956+ warning (
957+ position !== '' && position !== 'static' ,
958+ '<TouchHitTarget> inserts an empty absolutely positioned <div>. ' +
959+ 'This requires its parent DOM node to be positioned too, but the ' +
960+ 'parent DOM node was found to have the style "position" set to ' +
961+ 'either no value, or a value of "static". Try using a "position" ' +
962+ 'value of "relative".' ,
963+ ) ;
964+ warning (
965+ computedStyles . getPropertyValue ( 'zIndex' ) !== '' ,
966+ '<TouchHitTarget> inserts an empty <div> with "z-index" of "-1". ' +
967+ 'This requires its parent DOM node to have a "z-index" great than "-1",' +
968+ 'but the parent DOM node was found to no "z-index" value set.' +
969+ ' Try using a "z-index" value of "0" or greater.' ,
970+ ) ;
971+ }
912972 }
913973 }
914974}
0 commit comments