import type {DOMEventName} from '../events/DOMEventNames';
import type {ReactScopeInstance} from 'shared/ReactTypes';
import type {
ReactDOMEventHandle,
ReactDOMEventHandleListener,
} from './ReactDOMEventHandleTypes';
import {allNativeEvents} from '../events/EventRegistry';
import {
getEventHandlerListeners,
setEventHandlerListeners,
doesTargetHaveEventHandle,
addEventHandleToTarget,
} from './ReactDOMComponentTree';
import {ELEMENT_NODE} from './HTMLNodeType';
import {listenToNativeEventForNonManagedEventTarget} from '../events/DOMPluginEventSystem';
import {
enableScopeAPI,
enableCreateEventHandleAPI,
} from 'shared/ReactFeatureFlags';
type EventHandleOptions = {
capture?: boolean,
};
function isValidEventTarget(target: EventTarget | ReactScopeInstance): boolean {
return typeof (target: Object).addEventListener === 'function';
}
function isReactScope(target: EventTarget | ReactScopeInstance): boolean {
return typeof (target: Object).getChildContextValues === 'function';
}
function createEventHandleListener(
type: DOMEventName,
isCapturePhaseListener: boolean,
callback: (SyntheticEvent<EventTarget>) => void,
): ReactDOMEventHandleListener {
return {
callback,
capture: isCapturePhaseListener,
type,
};
}
function registerReactDOMEvent(
target: EventTarget | ReactScopeInstance,
domEventName: DOMEventName,
isCapturePhaseListener: boolean,
): void {
if ((target: any).nodeType === ELEMENT_NODE) {
} else if (enableScopeAPI && isReactScope(target)) {
} else if (isValidEventTarget(target)) {
const eventTarget = ((target: any): EventTarget);
listenToNativeEventForNonManagedEventTarget(
domEventName,
isCapturePhaseListener,
eventTarget,
);
} else {
throw new Error(
'ReactDOM.createEventHandle: setter called on an invalid ' +
'target. Provide a valid EventTarget or an element managed by React.',
);
}
}
export function createEventHandle(
type: string,
options?: EventHandleOptions,
): ReactDOMEventHandle {
if (enableCreateEventHandleAPI) {
const domEventName = ((type: any): DOMEventName);
if (!allNativeEvents.has(domEventName)) {
throw new Error(
`Cannot call unstable_createEventHandle with "${domEventName}", as it is not an event known to React.`,
);
}
let isCapturePhaseListener = false;
if (options != null) {
const optionsCapture = options.capture;
if (typeof optionsCapture === 'boolean') {
isCapturePhaseListener = optionsCapture;
}
}
const eventHandle: ReactDOMEventHandle = (
target: EventTarget | ReactScopeInstance,
callback: (SyntheticEvent<EventTarget>) => void,
) => {
if (typeof callback !== 'function') {
throw new Error(
'ReactDOM.createEventHandle: setter called with an invalid ' +
'callback. The callback must be a function.',
);
}
if (!doesTargetHaveEventHandle(target, eventHandle)) {
addEventHandleToTarget(target, eventHandle);
registerReactDOMEvent(target, domEventName, isCapturePhaseListener);
}
const listener = createEventHandleListener(
domEventName,
isCapturePhaseListener,
callback,
);
let targetListeners = getEventHandlerListeners(target);
if (targetListeners === null) {
targetListeners = new Set();
setEventHandlerListeners(target, targetListeners);
}
targetListeners.add(listener);
return () => {
((targetListeners: any): Set<ReactDOMEventHandleListener>).delete(
listener,
);
};
};
return eventHandle;
}
return (null: any);
}