From 4a6115560c36cc05f26678f8c6e4296d0b478cb0 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Mon, 20 Jan 2025 16:01:44 +0700 Subject: [PATCH 1/2] merge sx --- .../src/utils/mergeSlotProps.test.ts | 55 +++++++++++++++++++ .../mui-material/src/utils/mergeSlotProps.ts | 30 ++++++++-- 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/packages/mui-material/src/utils/mergeSlotProps.test.ts b/packages/mui-material/src/utils/mergeSlotProps.test.ts index baeaf8a77c633e..e52e7551030c8e 100644 --- a/packages/mui-material/src/utils/mergeSlotProps.test.ts +++ b/packages/mui-material/src/utils/mergeSlotProps.test.ts @@ -1,5 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; +import { SxProps } from '@mui/material/styles'; import mergeSlotProps from './mergeSlotProps'; @@ -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( @@ -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>( diff --git a/packages/mui-material/src/utils/mergeSlotProps.ts b/packages/mui-material/src/utils/mergeSlotProps.ts index a9c9ff0b888158..f4de7ef4041a39 100644 --- a/packages/mui-material/src/utils/mergeSlotProps.ts +++ b/packages/mui-material/src/utils/mergeSlotProps.ts @@ -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)?.className, - externalSlotProps?.className, - ); + const typedDefaultSlotProps = defaultSlotProps as Record; + const className = clsx(typedDefaultSlotProps?.className, externalSlotProps?.className); return { ...defaultSlotProps, ...externalSlotProps, ...(!!className && { className }), - ...((defaultSlotProps as Record)?.style && + ...(typedDefaultSlotProps?.style && externalSlotProps?.style && { - style: { ...(defaultSlotProps as Record).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; } From 8dfa551300bf8cb00578838c838904ad347d16ea Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Fri, 24 Jan 2025 17:24:13 +0700 Subject: [PATCH 2/2] update docs --- docs/data/material/guides/composition/composition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/material/guides/composition/composition.md b/docs/data/material/guides/composition/composition.md index 2398f114be463c..0108cb7de95acc 100644 --- a/docs/data/material/guides/composition/composition.md +++ b/docs/data/material/guides/composition/composition.md @@ -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