mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 11:17:19 +08:00
Master react (#18998)
* chore(): bump to beta 8 * fix(): IonFabButton href fix * fix(react): support components with href attributes * fix(): Prep work to break router out * fix(): breaking react-router and react-core into own packages * chore(): moving view stuff out of react-core * chore(): dev build 8-1 * chore(): update to react beta 8 * chore(): fixes to deps * fix(): removing IonAnchor in favor of IonRouterLink * chore(): beta 9 release * refactor(react): treeshake, minify, api * wip * fix(): react dev builds * fix(): fixes to get app builds working again * fix(): removing tgz file * feat(): adding platform helper methods * fix(): don't map attributes to props * chore(): add test app * feat(): copy css folder from core * chore(): move rollup node resolve to devDependencies * fix(): expose setupConfig() * perf(): improve treeshaking * fix(): removing crypto from generateUniqueId * fix(): adding missing rollup dp * fix(): test cleanup and fixes to make tests pass * chore(): moving react to packages folder * fix(): fixing react build due to move to packages * feat(): adding missing IonInfiniteScrollContent component * chore(): add automated testing using cypress * fix(): adding option onDidDismiss to controller components * 0.0.10 react * wip * fix(): removing deprecated React calls * fix(): exporting setupConfig from core * chore(): bump to 4.8.0-rc.0 * chore(): updating test-app deps and fixing test * chore(): updates to react readme
This commit is contained in:
83
packages/react/src/components/utils/attachEventProps.ts
Normal file
83
packages/react/src/components/utils/attachEventProps.ts
Normal file
@ -0,0 +1,83 @@
|
||||
export const attachEventProps = (node: HTMLElement, newProps: any, oldProps: any = {}) => {
|
||||
// add any classes in className to the class list
|
||||
const className = getClassName(node.classList, newProps, oldProps);
|
||||
if (className !== '') {
|
||||
node.className = className;
|
||||
}
|
||||
|
||||
Object.keys(newProps).forEach(name => {
|
||||
if (name === 'children' || name === 'style' || name === 'ref' || name === 'className') {
|
||||
return;
|
||||
}
|
||||
if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) {
|
||||
const eventName = name.substring(2);
|
||||
const eventNameLc = eventName[0].toLowerCase() + eventName.substring(1);
|
||||
|
||||
if (!isCoveredByReact(eventNameLc)) {
|
||||
syncEvent(node, eventNameLc, newProps[name]);
|
||||
}
|
||||
} else {
|
||||
(node as any)[name] = newProps[name];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const getClassName = (classList: DOMTokenList, newProps: any, oldProps: any) => {
|
||||
// map the classes to Maps for performance
|
||||
const currentClasses = arrayToMap(classList);
|
||||
const incomingPropClasses = arrayToMap(newProps.className ? newProps.className.split(' ') : []);
|
||||
const oldPropClasses = arrayToMap(oldProps.className ? oldProps.className.split(' ') : []);
|
||||
const finalClassNames: string[] = [];
|
||||
// loop through each of the current classes on the component
|
||||
// to see if it should be a part of the classNames added
|
||||
currentClasses.forEach(currentClass => {
|
||||
if (incomingPropClasses.has(currentClass)) {
|
||||
// add it as its already included in classnames coming in from newProps
|
||||
finalClassNames.push(currentClass);
|
||||
incomingPropClasses.delete(currentClass);
|
||||
} else if (!oldPropClasses.has(currentClass)) {
|
||||
// add it as it has NOT been removed by user
|
||||
finalClassNames.push(currentClass);
|
||||
}
|
||||
});
|
||||
incomingPropClasses.forEach(s => finalClassNames.push(s));
|
||||
return finalClassNames.join(' ');
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if an event is supported in the current execution environment.
|
||||
* @license Modernizr 3.0.0pre (Custom Build) | MIT
|
||||
*/
|
||||
export const isCoveredByReact = (eventNameSuffix: string, doc: Document = document) => {
|
||||
const eventName = 'on' + eventNameSuffix;
|
||||
let isSupported = eventName in doc;
|
||||
|
||||
if (!isSupported) {
|
||||
const element = doc.createElement('div');
|
||||
element.setAttribute(eventName, 'return;');
|
||||
isSupported = typeof (element as any)[eventName] === 'function';
|
||||
}
|
||||
|
||||
return isSupported;
|
||||
};
|
||||
|
||||
export const syncEvent = (node: Element, eventName: string, newEventHandler: (e: Event) => any) => {
|
||||
const eventStore = (node as any).__events || ((node as any).__events = {});
|
||||
const oldEventHandler = eventStore[eventName];
|
||||
|
||||
// Remove old listener so they don't double up.
|
||||
if (oldEventHandler) {
|
||||
node.removeEventListener(eventName, oldEventHandler);
|
||||
}
|
||||
|
||||
// Bind new listener.
|
||||
node.addEventListener(eventName, eventStore[eventName] = function handler(e: Event) {
|
||||
if (newEventHandler) { newEventHandler.call(this, e); }
|
||||
});
|
||||
};
|
||||
|
||||
const arrayToMap = (arr: string[] | DOMTokenList) => {
|
||||
const map = new Map<string, string>();
|
||||
(arr as string[]).forEach((s: string) => map.set(s, s));
|
||||
return map;
|
||||
};
|
Reference in New Issue
Block a user