Skip to content

Commit

Permalink
[material-ui][utils] Merge sx instead of override when using `merge…
Browse files Browse the repository at this point in the history
…SlotProps` (#45062)
  • Loading branch information
siriwatknp authored Jan 24, 2025
1 parent ad4825a commit bc2337f
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 7 deletions.
2 changes: 1 addition & 1 deletion docs/data/material/guides/composition/composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ The popper slot in the original example would now have both classes applied to i
:::
:::info
`style` object are shallow merged rather than replacing one another. The style keys from the first argument have higher priority.
`style` object and `sx` are shallow merged rather than replacing one another. Those values from the first argument have higher priority.
:::
## Component prop
Expand Down
55 changes: 55 additions & 0 deletions packages/mui-material/src/utils/mergeSlotProps.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { expect } from 'chai';
import { SxProps } from '@mui/material/styles';

import mergeSlotProps from './mergeSlotProps';

Expand Down Expand Up @@ -44,6 +45,31 @@ describe('utils/index.js', () => {
});
});

it('merge sx', () => {
expect(
mergeSlotProps<{ sx: SxProps }>(
{ sx: { color: 'red' } },
{ sx: { backgroundColor: 'blue' } },
),
).to.deep.equal({
sx: [{ backgroundColor: 'blue' }, { color: 'red' }],
});
});

it('merge sx array', () => {
expect(
mergeSlotProps<{ sx: SxProps }>(
{ sx: [{ color: 'red', '&.Mui-disabled': { opacity: 0 } }] },
{ sx: [{ backgroundColor: 'blue', '&.Mui-disabled': { opacity: 0.5 } }] },
),
).to.deep.equal({
sx: [
{ backgroundColor: 'blue', '&.Mui-disabled': { opacity: 0.5 } },
{ color: 'red', '&.Mui-disabled': { opacity: 0 } },
],
});
});

it('external slot props should override', () => {
expect(
mergeSlotProps<OwnerState>(
Expand Down Expand Up @@ -130,6 +156,35 @@ describe('utils/index.js', () => {
});
});

it('merge sx for callback', () => {
expect(
mergeSlotProps(
() => ({
sx: { color: 'red' },
}),
() => ({
sx: { backgroundColor: 'blue' },
}),
)(),
).to.deep.equal({
sx: [{ backgroundColor: 'blue' }, { color: 'red' }],
});
});

it('merge sx array for callback', () => {
expect(
mergeSlotProps(
() => ({ sx: [{ color: 'red', '&.Mui-disabled': { opacity: 0 } }] }),
() => ({ sx: [{ backgroundColor: 'blue', '&.Mui-disabled': { opacity: 0.5 } }] }),
)(),
).to.deep.equal({
sx: [
{ backgroundColor: 'blue', '&.Mui-disabled': { opacity: 0.5 } },
{ color: 'red', '&.Mui-disabled': { opacity: 0 } },
],
});
});

it('external callback should be called with default slot props', () => {
expect(
mergeSlotProps<(ownerState: OwnerState) => OwnerState>(
Expand Down
30 changes: 24 additions & 6 deletions packages/mui-material/src/utils/mergeSlotProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,38 @@ export default function mergeSlotProps<
externalSlotPropsValue?.style && {
style: { ...defaultSlotPropsValue.style, ...externalSlotPropsValue.style },
}),
...(defaultSlotPropsValue?.sx &&
externalSlotPropsValue?.sx && {
sx: [
...(Array.isArray(defaultSlotPropsValue.sx)
? defaultSlotPropsValue.sx
: [defaultSlotPropsValue.sx]),
...(Array.isArray(externalSlotPropsValue.sx)
? externalSlotPropsValue.sx
: [externalSlotPropsValue.sx]),
],
}),
};
}) as U;
}
const className = clsx(
(defaultSlotProps as Record<string, any>)?.className,
externalSlotProps?.className,
);
const typedDefaultSlotProps = defaultSlotProps as Record<string, any>;
const className = clsx(typedDefaultSlotProps?.className, externalSlotProps?.className);
return {
...defaultSlotProps,
...externalSlotProps,
...(!!className && { className }),
...((defaultSlotProps as Record<string, any>)?.style &&
...(typedDefaultSlotProps?.style &&
externalSlotProps?.style && {
style: { ...(defaultSlotProps as Record<string, any>).style, ...externalSlotProps.style },
style: { ...typedDefaultSlotProps.style, ...externalSlotProps.style },
}),
...(typedDefaultSlotProps?.sx &&
externalSlotProps?.sx && {
sx: [
...(Array.isArray(typedDefaultSlotProps.sx)
? typedDefaultSlotProps.sx
: [typedDefaultSlotProps.sx]),
...(Array.isArray(externalSlotProps.sx) ? externalSlotProps.sx : [externalSlotProps.sx]),
],
}),
} as U;
}

0 comments on commit bc2337f

Please sign in to comment.