Skip to content
This repository has been archived by the owner on Nov 17, 2022. It is now read-only.

Feat/support event transform #496

Merged
merged 10 commits into from
Sep 5, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/rax-compat/src/create-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { createElement as _createElement, useEffect, useCallback, useRef, useSta
import { cached, convertUnit } from 'style-unit';
import { observerElement } from './visibility';
import { isFunction, isObject, isNumber } from './type';
import transformPrototypes from './prototypes';


// https://github.com/alibaba/rax/blob/master/packages/driver-dom/src/index.js
Expand Down Expand Up @@ -100,6 +101,8 @@ export function createElement<P extends {
type = createInputCompat(type);
}

transformPrototypes(rest);

// Compat for visibility events.
if (isFunction(onAppear) || isFunction(onDisappear)) {
return _createElement(
Expand Down
118 changes: 118 additions & 0 deletions packages/rax-compat/src/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@

// Fork from https://github.com/facebook/react/blob/main/packages/react-dom/src/events/DOMEventProperties.js#L36
const events = [
'abort',
'auxClick',
'animationEnd',
'animationIteration',
'animationStart',
'cancel',
'canPlay',
'canPlayThrough',
'click',
'close',
'contextMenu',
'copy',
'cut',
'dblclick',
'drag',
'dragEnd',
'dragEnter',
'dragExit',
'dragLeave',
'dragOver',
'dragStart',
'drop',
'durationChange',
'emptied',
'encrypted',
'ended',
'error',
'gotPointerCapture',
'input',
'invalid',
'keyDown',
'keyPress',
'keyUp',
'load',
'loadedData',
'loadedMetadata',
'loadStart',
'lostPointerCapture',
'mouseDown',
'mouseMove',
'mouseOut',
'mouseOver',
'mouseUp',
'paste',
'pause',
'play',
'playing',
'pointerCancel',
'pointerDown',
'pointerMove',
'pointerOut',
'pointerOver',
'pointerUp',
'progress',
'rateChange',
'reset',
'resize',
'seeked',
'seeking',
'stalled',
'submit',
'suspend',
'transitionEnd',
'timeUpdate',
'touchCancel',
'touchEnd',
'touchStart',
'volumeChange',
'scroll',
'toggle',
'touchMove',
'waiting',
'wheel',
// EnterLeaveEventPlugin.registerEvents need't to convert to other bubbling events in rax compat,
// which are directly brokered, leaving the rest to React.
// https://github.com/facebook/react/blob/main/packages/react-dom/src/events/plugins/EnterLeaveEventPlugin.js#L29
'mouseEnter',
'mouseLeave',
'pointerEnter',
'pointerLeave',
// https://github.com/facebook/react/blob/main/packages/react-dom/src/events/plugins/ChangeEventPlugin.js#L37
'change',
// https://github.com/facebook/react/blob/main/packages/react-dom/src/events/plugins/SelectEventPlugin.js
'select',
// https://github.com/facebook/react/blob/main/packages/react-dom/src/events/plugins/BeforeInputEventPlugin.js
'beforeInput',
'compositionEnd',
'compositionStart',
'compositionUpdate',
];

// A map for transform event to react event.
// Such as ontouchstart transform to onTouchStart.
export const registrationNameToReactEvent = {};

registerEvents();

function registerDirectEvent(
registrationName: string,
reactEventName: string,
) {
registrationNameToReactEvent[`on${registrationName}`] = reactEventName;
}

export function registerEvents() {
for (let i = 0; i < events.length; i++) {
const eventName: string = events[i];
const domEventName: string = eventName.toLowerCase();
const capitalizedEvent = eventName[0].toUpperCase() + eventName.slice(1);
registerDirectEvent(domEventName, `on${capitalizedEvent}`);
}
// Special cases where event names don't match.
registerDirectEvent('dblclick', 'onDoubleClick');
}

21 changes: 21 additions & 0 deletions packages/rax-compat/src/prototypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { registrationNameToReactEvent } from './events';

export default function transformPrototypes(props: Object): void {
ClarkXia marked this conversation as resolved.
Show resolved Hide resolved
Object.keys(props).forEach((propKey: string) => {
// Transform the event so that it works properly in React.
// ontouchstart can work in rax, but react will check event in event plugin.
// Rax compat should transform event which can work in rax runtime.
// React support onDoubleClick but dblclick event is web Standards events.
// etc...
if (propKey.startsWith('on')) {
const lowerCasedPropkey: string = propKey.toLowerCase();
if (registrationNameToReactEvent.hasOwnProperty(lowerCasedPropkey)) {
const reactEvent: string = registrationNameToReactEvent[lowerCasedPropkey];
if (reactEvent !== propKey) {
props[reactEvent] = props[propKey];
delete props[propKey];
}
}
}
});
}