UNPKG

@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
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