@@ -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 ,
@@ -44,8 +44,13 @@ import {
4444import dangerousStyleValue from '../shared/dangerousStyleValue' ;
4545
4646import type { DOMContainer } from './ReactDOM' ;
47- import type { ReactEventResponder } from 'shared/ReactTypes' ;
47+ import type { ReactEventComponentInstance } from 'shared/ReactTypes' ;
48+ import {
49+ mountEventResponder ,
50+ unmountEventResponder ,
51+ } from '../events/DOMEventResponderSystem' ;
4852import { REACT_EVENT_TARGET_TOUCH_HIT } from 'shared/ReactSymbols' ;
53+ import { canUseDOM } from 'shared/ExecutionEnvironment' ;
4954
5055export type Type = string ;
5156export type Props = {
@@ -57,6 +62,23 @@ export type Props = {
5762 style ?: {
5863 display ?: string ,
5964 } ,
65+ bottom ?: null | number ,
66+ left ?: null | number ,
67+ right ?: null | number ,
68+ top ?: null | number ,
69+ } ;
70+ export type EventTargetChildElement = {
71+ type : string ,
72+ props : null | {
73+ style ?: {
74+ position ?: string ,
75+ zIndex ?: number ,
76+ bottom ?: string ,
77+ left ?: string ,
78+ right ?: string ,
79+ top ?: string ,
80+ } ,
81+ } ,
6082} ;
6183export type Container = Element | Document ;
6284export type Instance = Element ;
@@ -70,7 +92,6 @@ type HostContextDev = {
7092 eventData : null | { |
7193 isEventComponent ? : boolean ,
7294 isEventTarget ?: boolean ,
73- eventTargetType ?: null | Symbol | number ,
7495 | } ,
7596} ;
7697type HostContextProd = string ;
@@ -86,6 +107,8 @@ import {
86107} from 'shared/ReactFeatureFlags' ;
87108import warning from 'shared/warning' ;
88109
110+ const { html : HTML_NAMESPACE } = Namespaces ;
111+
89112// Intentionally not named imports because Rollup would
90113// use dynamic dispatch for CommonJS interop named imports.
91114const {
@@ -190,7 +213,6 @@ export function getChildHostContextForEventComponent(
190213 const eventData = {
191214 isEventComponent : true ,
192215 isEventTarget : false ,
193- eventTargetType : null ,
194216 } ;
195217 return { namespace, ancestorInfo, eventData} ;
196218 }
@@ -204,17 +226,24 @@ export function getChildHostContextForEventTarget(
204226 if ( __DEV__ ) {
205227 const parentHostContextDev = ( ( parentHostContext : any ) : HostContextDev ) ;
206228 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- ) ;
229+ if ( type === REACT_EVENT_TARGET_TOUCH_HIT ) {
230+ warning (
231+ parentHostContextDev . eventData === null ||
232+ ! parentHostContextDev . eventData . isEventComponent ,
233+ 'validateDOMNesting: <TouchHitTarget> cannot not be a direct child of an event component. ' +
234+ 'Ensure <TouchHitTarget> is a direct child of a DOM element.' ,
235+ ) ;
236+ const parentNamespace = parentHostContextDev . namespace ;
237+ if ( parentNamespace !== HTML_NAMESPACE ) {
238+ throw new Error (
239+ '<TouchHitTarget> was used in an unsupported DOM namespace. ' +
240+ 'Ensure the <TouchHitTarget> is used in an HTML namespace.' ,
241+ ) ;
242+ }
243+ }
214244 const eventData = {
215245 isEventComponent : false ,
216246 isEventTarget : true ,
217- eventTargetType : type ,
218247 } ;
219248 return { namespace, ancestorInfo, eventData} ;
220249 }
@@ -249,16 +278,6 @@ export function createInstance(
249278 if ( __DEV__ ) {
250279 // TODO: take namespace into account when validating.
251280 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- }
262281 validateDOMNesting ( type , null , hostContextDev . ancestorInfo ) ;
263282 if (
264283 typeof props . children === 'string' ||
@@ -365,25 +384,12 @@ export function createTextInstance(
365384 if ( enableEventAPI ) {
366385 const eventData = hostContextDev . eventData ;
367386 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- ) ;
374387 warning (
375388 ! eventData . isEventComponent ,
376389 'validateDOMNesting: React event components cannot have text DOM nodes as children. ' +
377390 'Wrap the child text "%s" in an element.' ,
378391 text ,
379392 ) ;
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- ) ;
387393 }
388394 }
389395 }
@@ -885,30 +891,105 @@ export function didNotFindHydratableSuspenseInstance(
885891 }
886892}
887893
888- export function handleEventComponent (
889- eventResponder : ReactEventResponder ,
890- rootContainerInstance : Container ,
891- internalInstanceHandle : Object ,
894+ export function mountEventComponent (
895+ eventComponentInstance : ReactEventComponentInstance ,
892896) : void {
893897 if ( enableEventAPI ) {
898+ mountEventResponder ( eventComponentInstance ) ;
899+ updateEventComponent ( eventComponentInstance ) ;
900+ }
901+ }
902+
903+ export function updateEventComponent (
904+ eventComponentInstance : ReactEventComponentInstance ,
905+ ) : void {
906+ if ( enableEventAPI ) {
907+ const rootContainerInstance = ( ( eventComponentInstance . rootInstance : any ) : Container ) ;
894908 const rootElement = rootContainerInstance . ownerDocument ;
895909 listenToEventResponderEventTypes (
896- eventResponder . targetEventTypes ,
910+ eventComponentInstance . responder . targetEventTypes ,
897911 rootElement ,
898912 ) ;
899913 }
900914}
901915
916+ export function unmountEventComponent (
917+ eventComponentInstance : ReactEventComponentInstance ,
918+ ) : void {
919+ if ( enableEventAPI ) {
920+ // TODO stop listening to targetEventTypes
921+ unmountEventResponder ( eventComponentInstance ) ;
922+ }
923+ }
924+
925+ export function getEventTargetChildElement (
926+ type : Symbol | number ,
927+ props : Props ,
928+ ) : null | EventTargetChildElement {
929+ if ( enableEventAPI ) {
930+ if ( type === REACT_EVENT_TARGET_TOUCH_HIT ) {
931+ const { bottom , left , right , top } = props ;
932+
933+ if ( ! bottom && ! left && ! right && ! top ) {
934+ return null ;
935+ }
936+ return {
937+ type : 'div ',
938+ props : {
939+ style : {
940+ position : 'absolute ',
941+ zIndex : - 1 ,
942+ bottom : bottom ? `- $ { bottom } px ` : '0 px ',
943+ left : left ? `- $ { left } px ` : '0 px ',
944+ right : right ? `- $ { right } px ` : '0 px ',
945+ top : top ? `- $ { top } px ` : '0 px ',
946+ } ,
947+ } ,
948+ } ;
949+ }
950+ }
951+ return null ;
952+ }
953+
902954export function handleEventTarget (
903955 type : Symbol | number ,
904956 props : Props ,
905- parentInstance : Container ,
957+ rootContainerInstance : Container ,
906958 internalInstanceHandle : Object ,
959+ ) : boolean {
960+ return false ;
961+ }
962+
963+ export function commitEventTarget (
964+ type : Symbol | number ,
965+ props : Props ,
966+ instance : Instance ,
967+ parentInstance : Instance ,
907968) : void {
908969 if ( enableEventAPI ) {
909- // Touch target hit slop handling
910970 if ( type === REACT_EVENT_TARGET_TOUCH_HIT ) {
911- // TODO
971+ if ( __DEV__ && canUseDOM ) {
972+ // This is done at DEV time because getComputedStyle will
973+ // typically force a style recalculation and force a layout,
974+ // reflow -– both of which are sync are expensive.
975+ const computedStyles = window . getComputedStyle ( parentInstance ) ;
976+ const position = computedStyles . getPropertyValue ( 'position' ) ;
977+ warning (
978+ position !== '' && position !== 'static' ,
979+ '<TouchHitTarget> inserts an empty absolutely positioned <div>. ' +
980+ 'This requires its parent DOM node to be positioned too, but the ' +
981+ 'parent DOM node was found to have the style "position" set to ' +
982+ 'either no value, or a value of "static". Try using a "position" ' +
983+ 'value of "relative".' ,
984+ ) ;
985+ warning (
986+ computedStyles . getPropertyValue ( 'zIndex' ) !== '' ,
987+ '<TouchHitTarget> inserts an empty <div> with "z-index" of "-1". ' +
988+ 'This requires its parent DOM node to have a "z-index" great than "-1",' +
989+ 'but the parent DOM node was found to no "z-index" value set.' +
990+ ' Try using a "z-index" value of "0" or greater.' ,
991+ ) ;
992+ }
912993 }
913994 }
914995}
0 commit comments