@wazespace/wme-react-components
Version:
A package with useful replications of the Waze Map Editor components to use in userscripts
79 lines • 3.46 kB
JavaScript
import { camelToDashCase } from './case-converters';
export function attachPropsToDOMElement(element, newProps, oldProps) {
const modifiedClassName = getClassName(element.classList, newProps, oldProps);
if (modifiedClassName)
element.className = modifiedClassName;
Object.keys(newProps).forEach((propKey) => {
if (propKey === 'children' ||
propKey === 'style' ||
propKey === 'ref' ||
propKey === 'class' ||
propKey === 'className' ||
propKey === 'forwardedRef')
return;
const propValue = newProps[propKey];
if (propKey.startsWith('on') && propKey[2] === propKey[2].toUpperCase()) {
// this is an event handler registrar
const eventName = propKey.substring(2);
const normalizedEventName = eventName.charAt(0).toLowerCase() + eventName.substring(1);
if (!isEventCoveredByReact(normalizedEventName)) {
syncEvent(element, normalizedEventName, propValue);
}
return;
}
element[propKey] = propValue;
// non-event property (attribute)
if (typeof propValue === 'string') {
// we can deal with it and assign as an attribute
const attributeName = camelToDashCase(propKey);
element.setAttribute(attributeName, propValue);
}
});
}
function getClassName(classList, newProps, oldProps) {
const includeClassNames = newProps.className || newProps.class;
const excludeClassNames = oldProps.className || oldProps.class;
const classListTokenSet = new Set(classList);
const includeClassNamesSet = new Set(includeClassNames?.split?.(' ') ?? []);
const excludeClassNamesSet = new Set(excludeClassNames?.split?.(' ') ?? []);
const classNamesToJoin = [];
classListTokenSet.forEach((token) => {
if (includeClassNamesSet.has(token)) {
classNamesToJoin.push(token);
includeClassNamesSet.delete(token);
}
else if (!excludeClassNamesSet.has(token)) {
classNamesToJoin.push(token);
}
});
includeClassNamesSet.forEach((className) => classNamesToJoin.push(className));
return classNamesToJoin.join(' ');
}
function transformReactEventName(eventName) {
if (eventName === 'doubleclick')
return 'dblclick';
return eventName;
}
export function isEventCoveredByReact(eventName) {
if (typeof document === 'undefined')
return true;
const properEventName = transformReactEventName(eventName);
const properEventPropertyName = 'on' + properEventName;
if (properEventPropertyName in document)
return true;
const dummyElement = document.createElement('div');
dummyElement.setAttribute(properEventPropertyName, 'return;');
return typeof dummyElement[properEventPropertyName] === 'function';
}
function syncEvent(element, eventName, eventHandler) {
const eventsRepository = element.__events || (element.__events = {});
const registeredEventHandler = eventsRepository[eventName];
if (registeredEventHandler)
element.removeEventListener(eventName, registeredEventHandler);
const newEventHandler = function (event) {
eventHandler?.call(this, event);
};
eventsRepository[eventName] = newEventHandler;
element.addEventListener(eventName, newEventHandler);
}
//# sourceMappingURL=custom-element-synchronizer.js.map