UNPKG

@base-ui-components/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

71 lines (70 loc) 2.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.mergeReactProps = mergeReactProps; /** * Merges multiple sets of React props such that their event handlers are called in sequence (the user's * before our internal ones), and allows the user to prevent the internal event handlers from being * executed by attaching a `preventBaseUIHandler` method. It also merges the `style` prop, whereby * the user's styles overwrite the internal ones. * @important **`className` and `ref` are not merged.** * @param externalProps the user's external props. * @param internalProps our own internal props. * @returns the merged props. */ function mergeReactProps(externalProps, ...internalProps) { let mergedInternalProps = internalProps[0]; for (let i = 1; i < internalProps.length; i += 1) { mergedInternalProps = merge(mergedInternalProps, internalProps[i]); } return merge(externalProps, mergedInternalProps); } function merge(externalProps, internalProps) { if (!externalProps) { return internalProps; } return Object.entries(externalProps).reduce((acc, [key, value]) => { if ( // This approach is more efficient than using a regex. key[0] === 'o' && key[1] === 'n' && key.charCodeAt(2) >= 65 /* A */ && key.charCodeAt(2) <= 90 /* Z */ && typeof value === 'function') { acc[key] = event => { let isPrevented = false; const theirHandler = value; const ourHandler = internalProps[key]; const baseUIEvent = event; baseUIEvent.preventBaseUIHandler = () => { isPrevented = true; }; const result = theirHandler(baseUIEvent); if (!isPrevented) { ourHandler?.(baseUIEvent); } return result; }; } else if (key === 'style') { if (value || internalProps.style) { acc[key] = { ...internalProps.style, ...(value || {}) }; } } else if (key === 'className') { if (value) { if (internalProps.className) { // eslint-disable-next-line prefer-template acc[key] = value + ' ' + internalProps.className; } else { acc[key] = value; } } else { acc[key] = internalProps.className; } } else { acc[key] = value; } return acc; }, { ...internalProps }); }