@@ -33,7 +33,7 @@ import {
33
33
isEnabled as ReactBrowserEventEmitterIsEnabled ,
34
34
setEnabled as ReactBrowserEventEmitterSetEnabled ,
35
35
} from '../events/ReactBrowserEventEmitter' ;
36
- import { getChildNamespace } from '../shared/DOMNamespaces' ;
36
+ import { Namespaces , getChildNamespace } from '../shared/DOMNamespaces' ;
37
37
import {
38
38
ELEMENT_NODE ,
39
39
TEXT_NODE ,
@@ -46,6 +46,7 @@ import dangerousStyleValue from '../shared/dangerousStyleValue';
46
46
import type { DOMContainer } from './ReactDOM' ;
47
47
import type { ReactEventResponder } from 'shared/ReactTypes' ;
48
48
import { REACT_EVENT_TARGET_TOUCH_HIT } from 'shared/ReactSymbols' ;
49
+ import { canUseDOM } from 'shared/ExecutionEnvironment' ;
49
50
50
51
export type Type = string ;
51
52
export type Props = {
@@ -57,6 +58,23 @@ export type Props = {
57
58
style ?: {
58
59
display ?: string ,
59
60
} ,
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
+ } ,
60
78
} ;
61
79
export type Container = Element | Document ;
62
80
export type Instance = Element ;
@@ -70,7 +88,6 @@ type HostContextDev = {
70
88
eventData : null | { |
71
89
isEventComponent ? : boolean ,
72
90
isEventTarget ?: boolean ,
73
- eventTargetType ?: null | Symbol | number ,
74
91
| } ,
75
92
} ;
76
93
type HostContextProd = string ;
@@ -86,6 +103,8 @@ import {
86
103
} from 'shared/ReactFeatureFlags' ;
87
104
import warning from 'shared/warning' ;
88
105
106
+ const { html : HTML_NAMESPACE } = Namespaces ;
107
+
89
108
// Intentionally not named imports because Rollup would
90
109
// use dynamic dispatch for CommonJS interop named imports.
91
110
const {
@@ -190,7 +209,6 @@ export function getChildHostContextForEventComponent(
190
209
const eventData = {
191
210
isEventComponent : true ,
192
211
isEventTarget : false ,
193
- eventTargetType : null ,
194
212
} ;
195
213
return { namespace, ancestorInfo, eventData} ;
196
214
}
@@ -204,17 +222,24 @@ export function getChildHostContextForEventTarget(
204
222
if ( __DEV__ ) {
205
223
const parentHostContextDev = ( ( parentHostContext : any ) : HostContextDev ) ;
206
224
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
+ }
214
240
const eventData = {
215
241
isEventComponent : false ,
216
242
isEventTarget : true ,
217
- eventTargetType : type ,
218
243
} ;
219
244
return { namespace, ancestorInfo, eventData} ;
220
245
}
@@ -249,16 +274,6 @@ export function createInstance(
249
274
if ( __DEV__ ) {
250
275
// TODO: take namespace into account when validating.
251
276
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
- }
262
277
validateDOMNesting ( type , null , hostContextDev . ancestorInfo ) ;
263
278
if (
264
279
typeof props . children === 'string' ||
@@ -365,25 +380,12 @@ export function createTextInstance(
365
380
if ( enableEventAPI ) {
366
381
const eventData = hostContextDev . eventData ;
367
382
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
- ) ;
374
383
warning (
375
384
! eventData . isEventComponent ,
376
385
'validateDOMNesting: React event components cannot have text DOM nodes as children. ' +
377
386
'Wrap the child text "%s" in an element.' ,
378
387
text ,
379
388
) ;
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
- ) ;
387
389
}
388
390
}
389
391
}
@@ -899,16 +901,74 @@ export function handleEventComponent(
899
901
}
900
902
}
901
903
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
+
902
933
export function handleEventTarget (
903
934
type : Symbol | number ,
904
935
props : Props ,
905
- parentInstance : Container ,
936
+ rootContainerInstance : Container ,
906
937
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 ,
907
947
) : void {
908
948
if ( enableEventAPI ) {
909
- // Touch target hit slop handling
910
949
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
+ }
912
972
}
913
973
}
914
974
}
0 commit comments