@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
JavaScript
;
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
});
}