@project44-manifest/react
Version:
Manifest Design System react components
54 lines (46 loc) • 1.75 kB
text/typescript
import clsx from 'clsx';
import isObject from 'lodash.isobject';
import { mergeCallbacks } from './mergeCallbacks';
import type { Callback, Props, TupleTypes, UnionToIntersection } from './types';
/**
* Merge multiple sets of props together
*
* Adapted from react-aria to support style objects
* https://github.com/adobe/react-spectrum/blob/main/packages/%40react-aria/utils/src/mergeProps.ts
*/
export function mergeProps<T extends Props[]>(...args: T): UnionToIntersection<TupleTypes<T>> {
const result: Record<string, unknown> = { ...args[0] };
for (let i = 1; i < args.length; i += 1) {
const props: Record<string, unknown> = args[i];
for (const prop in props) {
if (Object.prototype.hasOwnProperty.call(props, prop)) {
const mergedValue = result[prop];
const propValue = props[prop];
// Merge classNames
if (
prop === 'className' &&
typeof mergedValue === 'string' &&
typeof propValue === 'string'
) {
result[prop] = clsx(mergedValue, propValue);
// Merge styles
} else if (prop === 'style' && isObject(mergedValue) && isObject(propValue)) {
result[prop] = { ...mergedValue, ...propValue };
// Merge event handlers that start with `on`
} else if (
typeof mergedValue === 'function' &&
typeof propValue === 'function' &&
/^on[A-Z]/.test(prop)
) {
result[prop] = mergeCallbacks(
mergedValue as Callback<unknown[]>,
propValue as Callback<unknown[]>,
);
} else {
result[prop] = propValue ?? mergedValue;
}
}
}
}
return result as UnionToIntersection<TupleTypes<T>>;
}