| 39 | * @param args - Multiple sets of props to merge together. |
| 40 | */ |
| 41 | export function mergeProps<T extends PropsArg[]>(...args: T): UnionToIntersection<TupleTypes<T>> { |
| 42 | // Start with a base clone of the first argument. This is a lot faster than starting |
| 43 | // with an empty object and adding properties as we go. |
| 44 | let result: Props = {...args[0]}; |
| 45 | for (let i = 1; i < args.length; i++) { |
| 46 | let props = args[i]; |
| 47 | for (let key in props) { |
| 48 | let a = result[key]; |
| 49 | let b = props[key]; |
| 50 | |
| 51 | // Chain events |
| 52 | if ( |
| 53 | typeof a === 'function' && |
| 54 | typeof b === 'function' && |
| 55 | // This is a lot faster than a regex. |
| 56 | key[0] === 'o' && |
| 57 | key[1] === 'n' && |
| 58 | key.charCodeAt(2) >= /* 'A' */ 65 && |
| 59 | key.charCodeAt(2) <= /* 'Z' */ 90 |
| 60 | ) { |
| 61 | result[key] = chain(a, b); |
| 62 | |
| 63 | // Merge classnames, sometimes classNames are empty string which eval to false, so we just need to do a type check |
| 64 | } else if ( |
| 65 | (key === 'className' || key === 'UNSAFE_className') && |
| 66 | typeof a === 'string' && |
| 67 | typeof b === 'string' |
| 68 | ) { |
| 69 | result[key] = clsx(a, b); |
| 70 | } else if (key === 'id' && a && b) { |
| 71 | result.id = mergeIds(a, b); |
| 72 | } else if (key === 'ref' && a && b) { |
| 73 | result.ref = mergeRefs(a, b); |
| 74 | // Override others |
| 75 | } else { |
| 76 | result[key] = b !== undefined ? b : a; |
| 77 | } |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | return result as UnionToIntersection<TupleTypes<T>>; |
| 82 | } |