Skip to content

Commit a012aa1

Browse files
committed
Merge branch 'master' into fabric-measure-calls
2 parents cd087b0 + c7a9599 commit a012aa1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3224
-923
lines changed

packages/events/EventTypes.js

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,44 @@
1010
import type {AnyNativeEvent} from 'events/PluginModuleType';
1111
import type {ReactEventResponderEventType} from 'shared/ReactTypes';
1212

13-
export type EventResponderContext = {
14-
event: AnyNativeEvent,
15-
eventTarget: Element | Document,
16-
eventType: string,
17-
isPassive: () => boolean,
18-
isPassiveSupported: () => boolean,
19-
dispatchEvent: <E>(
20-
eventObject: E,
21-
{
22-
capture?: boolean,
23-
discrete?: boolean,
24-
stopPropagation?: boolean,
25-
},
13+
export type ResponderEvent = {
14+
nativeEvent: AnyNativeEvent,
15+
target: Element | Document,
16+
type: string,
17+
passive: boolean,
18+
passiveSupported: boolean,
19+
};
20+
21+
export type ResponderDispatchEventOptions = {
22+
capture?: boolean,
23+
discrete?: boolean,
24+
stopPropagation?: boolean,
25+
};
26+
27+
export type ResponderContext = {
28+
dispatchEvent: (
29+
eventObject: Object,
30+
otpions: ResponderDispatchEventOptions,
2631
) => void,
2732
isTargetWithinElement: (
2833
childTarget: Element | Document,
2934
parentTarget: Element | Document,
3035
) => boolean,
31-
isTargetOwned: (Element | Document) => boolean,
3236
isTargetWithinEventComponent: (Element | Document) => boolean,
33-
isPositionWithinTouchHitTarget: (x: number, y: number) => boolean,
37+
isPositionWithinTouchHitTarget: (
38+
doc: Document,
39+
x: number,
40+
y: number,
41+
) => boolean,
3442
addRootEventTypes: (
43+
document: Document,
3544
rootEventTypes: Array<ReactEventResponderEventType>,
3645
) => void,
3746
removeRootEventTypes: (
3847
rootEventTypes: Array<ReactEventResponderEventType>,
3948
) => void,
40-
requestOwnership: (target: Element | Document | null) => boolean,
41-
releaseOwnership: (target: Element | Document | null) => boolean,
42-
withAsyncDispatching: (func: () => void) => void,
49+
hasOwnership: () => boolean,
50+
requestOwnership: () => boolean,
51+
releaseOwnership: () => boolean,
52+
setTimeout: (func: () => void, timeout: number) => TimeoutID,
4353
};

packages/react-art/src/ReactARTHostConfig.js

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import * as Scheduler from 'scheduler';
1111
import invariant from 'shared/invariant';
1212

1313
import {TYPES, EVENT_TYPES, childrenAsString} from './ReactARTInternals';
14+
import type {ReactEventComponentInstance} from 'shared/ReactTypes';
1415

1516
// Intentionally not named imports because Rollup would
1617
// use dynamic dispatch for CommonJS interop named imports.
@@ -439,19 +440,45 @@ export function unhideTextInstance(textInstance, text): void {
439440
// Noop
440441
}
441442

442-
export function handleEventComponent(
443-
eventResponder: ReactEventResponder,
444-
rootContainerInstance: Container,
445-
internalInstanceHandle: Object,
443+
export function mountEventComponent(
444+
eventComponentInstance: ReactEventComponentInstance,
445+
) {
446+
throw new Error('Not yet implemented.');
447+
}
448+
449+
export function updateEventComponent(
450+
eventComponentInstance: ReactEventComponentInstance,
446451
) {
447-
// TODO: add handleEventComponent implementation
452+
throw new Error('Not yet implemented.');
453+
}
454+
455+
export function unmountEventComponent(
456+
eventComponentInstance: ReactEventComponentInstance,
457+
): void {
458+
throw new Error('Not yet implemented.');
459+
}
460+
461+
export function getEventTargetChildElement(
462+
type: Symbol | number,
463+
props: Props,
464+
): null {
465+
throw new Error('Not yet implemented.');
448466
}
449467

450468
export function handleEventTarget(
451469
type: Symbol | number,
452470
props: Props,
453-
parentInstance: Container,
471+
rootContainerInstance: Container,
454472
internalInstanceHandle: Object,
455-
) {
456-
// TODO: add handleEventTarget implementation
473+
): boolean {
474+
throw new Error('Not yet implemented.');
475+
}
476+
477+
export function commitEventTarget(
478+
type: Symbol | number,
479+
props: Props,
480+
instance: Instance,
481+
parentInstance: Instance,
482+
): void {
483+
throw new Error('Not yet implemented.');
457484
}

packages/react-dom/src/client/ReactDOMHostConfig.js

Lines changed: 124 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -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';
3737
import {
3838
ELEMENT_NODE,
3939
TEXT_NODE,
@@ -44,8 +44,13 @@ import {
4444
import dangerousStyleValue from '../shared/dangerousStyleValue';
4545

4646
import 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';
4852
import {REACT_EVENT_TARGET_TOUCH_HIT} from 'shared/ReactSymbols';
53+
import {canUseDOM} from 'shared/ExecutionEnvironment';
4954

5055
export type Type = string;
5156
export 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
};
6183
export type Container = Element | Document;
6284
export 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
};
7697
type HostContextProd = string;
@@ -86,6 +107,8 @@ import {
86107
} from 'shared/ReactFeatureFlags';
87108
import 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.
91114
const {
@@ -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` : '0px',
943+
left: left ? `-${left}px` : '0px',
944+
right: right ? `-${right}px` : '0px',
945+
top: top ? `-${top}px` : '0px',
946+
},
947+
},
948+
};
949+
}
950+
}
951+
return null;
952+
}
953+
902954
export 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

Comments
 (0)