diff --git a/docs/types/theme-augment.d.ts b/docs/types/theme-augment.d.ts new file mode 100644 index 00000000000000..3df1e6fa43e3ea --- /dev/null +++ b/docs/types/theme-augment.d.ts @@ -0,0 +1,6 @@ +import type { Theme } from '@mui/material/styles'; +import type { Components } from '@mui/material/stylesDeprecated'; + +declare module '@mui/material/styles' { + interface ThemeComponents extends Components {} +} diff --git a/packages/mui-docs/src/branding/brandingTheme.ts b/packages/mui-docs/src/branding/brandingTheme.ts index 07d04b4f643934..401fd7fd3345e2 100644 --- a/packages/mui-docs/src/branding/brandingTheme.ts +++ b/packages/mui-docs/src/branding/brandingTheme.ts @@ -2,12 +2,15 @@ import type { CSSObject } from '@mui/system'; import type {} from '@mui/material/themeCssVarsAugmentation'; import ArrowDropDownRounded from '@mui/icons-material/ArrowDropDownRounded'; import { createTheme, ThemeOptions, Theme, alpha } from '@mui/material/styles'; +import { Components } from '@mui/material/stylesDeprecated'; interface ApplyDarkStyles { (scheme: CSSObject): CSSObject; } declare module '@mui/material/styles' { + interface ThemeComponents extends Components {} + interface Theme { applyDarkStyles: ApplyDarkStyles; } diff --git a/packages/mui-lab/src/themeAugmentation/components.ts b/packages/mui-lab/src/themeAugmentation/components.ts index 4dd31b61b92d4d..75081747958cef 100644 --- a/packages/mui-lab/src/themeAugmentation/components.ts +++ b/packages/mui-lab/src/themeAugmentation/components.ts @@ -2,8 +2,8 @@ import { ComponentsProps, ComponentsOverrides, ComponentsVariants, - Theme as MuiTheme, -} from '@mui/material/styles'; +} from '@mui/material/stylesDeprecated'; +import { Theme as MuiTheme } from '@mui/material/styles'; type Theme = Omit; @@ -68,6 +68,6 @@ export interface LabComponents { }; } -declare module '@mui/material/styles' { +declare module '@mui/material/stylesDeprecated' { interface Components extends LabComponents {} } diff --git a/packages/mui-lab/src/themeAugmentation/overrides.ts b/packages/mui-lab/src/themeAugmentation/overrides.ts index 7e8c81418ed3ac..2c833f57ec7c33 100644 --- a/packages/mui-lab/src/themeAugmentation/overrides.ts +++ b/packages/mui-lab/src/themeAugmentation/overrides.ts @@ -25,7 +25,7 @@ export interface LabComponentNameToClassKey { MuiTimelineSeparator: TimelineSeparatorClassKey; } -declare module '@mui/material/styles' { +declare module '@mui/material/stylesDeprecated' { interface ComponentNameToClassKey extends LabComponentNameToClassKey {} } diff --git a/packages/mui-lab/src/themeAugmentation/props.ts b/packages/mui-lab/src/themeAugmentation/props.ts index 28a95d3a1f2744..bb24648506a8ef 100644 --- a/packages/mui-lab/src/themeAugmentation/props.ts +++ b/packages/mui-lab/src/themeAugmentation/props.ts @@ -24,7 +24,7 @@ export interface LabComponentsPropsList { MuiTimelineSeparator: TimelineSeparatorProps; } -declare module '@mui/material/styles' { +declare module '@mui/material/stylesDeprecated' { interface ComponentsPropsList extends LabComponentsPropsList {} } diff --git a/packages/mui-material/perf-test/README.md b/packages/mui-material/perf-test/README.md new file mode 100644 index 00000000000000..70c61348b23ba3 --- /dev/null +++ b/packages/mui-material/perf-test/README.md @@ -0,0 +1,61 @@ +# TypeScript Performance Test + +Run TypeScript performance diagnostics for `createTheme` to measure type instantiation costs. + +## Prerequisites + +```bash +npm install -g @typescript/analyze-trace +``` + +## Run Performance Test + +```bash +cd packages/mui-material/perf-test +``` + +### 1. Run Basic Diagnostics + +```bash +npx tsc --noEmit --diagnostics +``` + +Key metrics to note: + +- `Instantiations` (target: < 500,000) +- `Memory used` (target: < 300MB) +- `Check time` (lower is better) + +### 2. Generate Trace + +```bash +npx tsc --noEmit --generateTrace trace-output --incremental false +``` + +### 3. Analyze Trace + +```bash +analyze-trace trace-output +``` + +Look for: + +- Top instantiated types +- Hottest files +- Memory allocation patterns + +### 4. Visual Analysis (Optional) + +1. Open Chrome: `chrome://tracing` +2. Load `trace-output/trace.json` +3. Find repeated `Components>` instantiations + +## Files + +- `test-createTheme.ts` - Test file that triggers the circular dependency +- `tsconfig.json` - TypeScript configuration +- `trace-output/` - Generated trace files + +## More Details + +See `.claude/typescript-performance-diagnosis.md` for comprehensive guide. diff --git a/packages/mui-material/perf-test/test-createTheme.ts b/packages/mui-material/perf-test/test-createTheme.ts new file mode 100644 index 00000000000000..738bbd3f4d044c --- /dev/null +++ b/packages/mui-material/perf-test/test-createTheme.ts @@ -0,0 +1,16 @@ +import { ButtonTheme } from '@mui/material/Button'; +import { createTheme } from '../src/styles'; + +declare module '@mui/material/styles' { + interface ThemeComponents extends ButtonTheme {} +} + +export default createTheme({ + components: { + MuiButton: { + defaultProps: { + disableElevation: true, + }, + }, + }, +}); diff --git a/packages/mui-material/perf-test/tsconfig.json b/packages/mui-material/perf-test/tsconfig.json new file mode 100644 index 00000000000000..2386878f58ba2c --- /dev/null +++ b/packages/mui-material/perf-test/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.json", + "include": ["test-createTheme.ts"], + "compilerOptions": { + "moduleResolution": "Bundler" + } +} diff --git a/packages/mui-material/src/Button/Button.d.ts b/packages/mui-material/src/Button/Button.d.ts index 0e32a0b6ab459e..95b8a13a065d78 100644 --- a/packages/mui-material/src/Button/Button.d.ts +++ b/packages/mui-material/src/Button/Button.d.ts @@ -1,10 +1,10 @@ import * as React from 'react'; import { DistributiveOmit, OverridableStringUnion } from '@mui/types'; import { SxProps } from '@mui/system'; -import { Theme } from '../styles'; +import { Theme, CreateThemeComponent } from '../styles'; import { ExtendButtonBase, ExtendButtonBaseTypeMap } from '../ButtonBase'; import { OverrideProps, OverridableComponent, OverridableTypeMap } from '../OverridableComponent'; -import { ButtonClasses } from './buttonClasses'; +import { ButtonClasses, ButtonClassKey } from './buttonClasses'; export interface ButtonPropsVariantOverrides {} @@ -146,4 +146,8 @@ export type ButtonProps< component?: React.ElementType; }; +export type ButtonTheme = { + MuiButton: CreateThemeComponent; +}; + export default Button; diff --git a/packages/mui-material/src/DefaultPropsProvider/DefaultPropsProvider.tsx b/packages/mui-material/src/DefaultPropsProvider/DefaultPropsProvider.tsx index ecfd3b1c56df14..63e165a5e1cf3e 100644 --- a/packages/mui-material/src/DefaultPropsProvider/DefaultPropsProvider.tsx +++ b/packages/mui-material/src/DefaultPropsProvider/DefaultPropsProvider.tsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import SystemDefaultPropsProvider, { useDefaultProps as useSystemDefaultProps, } from '@mui/system/DefaultPropsProvider'; -import type { ComponentsPropsList } from '../styles/props'; +import type { ComponentsPropsList } from '../stylesDeprecated/props'; function DefaultPropsProvider( props: React.PropsWithChildren<{ diff --git a/packages/mui-material/src/locale/utils/LocaleTextApi.ts b/packages/mui-material/src/locale/utils/LocaleTextApi.ts index 5a5ecebfacfbb1..121c3ce52c6076 100644 --- a/packages/mui-material/src/locale/utils/LocaleTextApi.ts +++ b/packages/mui-material/src/locale/utils/LocaleTextApi.ts @@ -1,4 +1,4 @@ -import { ComponentsPropsList } from '../../styles/props'; +import { ComponentsPropsList } from '../../stylesDeprecated/props'; export interface Localization { components?: { diff --git a/packages/mui-material/src/styles/createTheme.ts b/packages/mui-material/src/styles/createTheme.ts index 5558656f9ac4bc..de902dd11dc073 100644 --- a/packages/mui-material/src/styles/createTheme.ts +++ b/packages/mui-material/src/styles/createTheme.ts @@ -11,7 +11,8 @@ import createThemeNoVars, { ThemeOptions as ThemeNoVarsOptions, } from './createThemeNoVars'; -export type { Theme, CssThemeVariables } from './createThemeNoVars'; +export type { Theme, CssThemeVariables, CreateThemeComponent } from './createThemeNoVars'; +export type { ThemeComponents } from './createThemeFoundation'; type CssVarsOptions = CssThemeVariables extends { enabled: true; diff --git a/packages/mui-material/src/styles/createThemeFoundation.ts b/packages/mui-material/src/styles/createThemeFoundation.ts index 6c8df594dd976a..85b174589828a4 100644 --- a/packages/mui-material/src/styles/createThemeFoundation.ts +++ b/packages/mui-material/src/styles/createThemeFoundation.ts @@ -33,6 +33,11 @@ export type ExtendedColorScheme = OverridableStringUnion, CssVarsOptions { mixins?: MixinsOptions; - components?: Components>; + components?: ThemeComponents; palette?: PaletteOptions; shadows?: Shadows; transitions?: TransitionsOptions; @@ -82,7 +87,7 @@ type CssVarsProperties = CssThemeVariables extends { enabled: true } */ export interface Theme extends BaseTheme, CssVarsProperties { cssVariables?: false; - components?: Components; + components?: ThemeComponents; unstable_sx: (props: SxProps) => CSSObject; unstable_sxConfig: SxConfig; alpha: (color: string, value: number | string) => string; @@ -90,6 +95,33 @@ export interface Theme extends BaseTheme, CssVarsProperties { darken: (color: string, coefficient: number | string) => string; } +export type CreateThemeComponent = { + defaultProps?: Partial; + styleOverrides?: Record< + SlotNames, + Interpolation< + // Record is for other props that the slot receive internally + // Documenting all ownerStates could be a huge work, let's wait until we have a real needs from developers. + Props & + Record & { + ownerState: OwnerState & Record; + } & { + theme: Theme; + } & Record + > + >; + variants?: Array<{ + props: + | Partial + | (( + props: Partial & { + ownerState: Partial; + }, + ) => boolean); + style: Interpolation<{ theme: Theme }>; + }>; +}; + /** * Generate a theme base on the options received. * @param options Takes an incomplete theme object and adds the missing parts. diff --git a/packages/mui-material/src/styles/createThemeWithVars.d.ts b/packages/mui-material/src/styles/createThemeWithVars.d.ts index 16f1891bae49aa..15272a17bd325e 100644 --- a/packages/mui-material/src/styles/createThemeWithVars.d.ts +++ b/packages/mui-material/src/styles/createThemeWithVars.d.ts @@ -1,5 +1,4 @@ import { ThemeOptions, Theme } from './createThemeNoVars'; -import { Components } from './components'; import { DefaultColorScheme, ColorSchemeOverrides, @@ -31,10 +30,10 @@ import { ColorSystemOptions, CssVarsPalette, ColorSystem, + CssVarsTheme, ThemeVars, ThemeCssVarOverrides, ThemeCssVar, - CssVarsTheme, } from './createThemeFoundation'; // Re-export all types from foundation to maintain backward compatibility @@ -75,7 +74,7 @@ export type { CssVarsTheme, }; -export interface CssVarsThemeOptions extends Omit { +export interface CssVarsThemeOptions extends Omit { /** * The strategy to generate CSS variables * @@ -123,10 +122,6 @@ export interface CssVarsThemeOptions extends Omit & CssVarsTheme>; /** * Color schemes configuration */ diff --git a/packages/mui-material/src/styles/index.d.ts b/packages/mui-material/src/styles/index.d.ts index 990e9e97ebaba2..9b6f776283b166 100644 --- a/packages/mui-material/src/styles/index.d.ts +++ b/packages/mui-material/src/styles/index.d.ts @@ -6,9 +6,10 @@ export { default as unstable_createMuiStrictModeTheme, ThemeOptions, Theme, + ThemeComponents, CssThemeVariables, + CreateThemeComponent, } from './createTheme'; -export { default as adaptV4Theme, DeprecatedThemeOptions } from './adaptV4Theme'; export { Shadows } from './shadows'; export { ZIndex } from './zIndex'; export { @@ -80,10 +81,6 @@ export { default as useThemeProps } from './useThemeProps'; export * from './useThemeProps'; export { default as styled } from './styled'; export { default as ThemeProvider, ThemeProviderProps } from './ThemeProvider'; -export { ComponentsProps, ComponentsPropsList } from './props'; -export { ComponentsVariants } from './variants'; -export { ComponentsOverrides, ComponentNameToClassKey } from './overrides'; -export { Components } from './components'; export { getUnit as unstable_getUnit, toUnitless as unstable_toUnitless } from './cssUtils'; export type ClassNameMap = Record; diff --git a/packages/mui-material/src/styles/index.js b/packages/mui-material/src/styles/index.js index e670636d7b4e67..6b3057cd4c90f1 100644 --- a/packages/mui-material/src/styles/index.js +++ b/packages/mui-material/src/styles/index.js @@ -1,5 +1,4 @@ export { default as THEME_ID } from './identifier'; -export { default as adaptV4Theme } from './adaptV4Theme'; export { hexToRgb, rgbToHex, diff --git a/packages/mui-material/src/styles/useThemeProps.d.ts b/packages/mui-material/src/styles/useThemeProps.d.ts index eeb19e5f965f59..12718b9e256d9e 100644 --- a/packages/mui-material/src/styles/useThemeProps.d.ts +++ b/packages/mui-material/src/styles/useThemeProps.d.ts @@ -1,8 +1,7 @@ -import { Theme } from './createTheme'; -import { Components } from './components'; +import { ThemeComponents } from './createThemeFoundation'; export interface ThemeWithProps { - components?: Components>; + components?: ThemeComponents; } export type ThemedProps = Theme extends { diff --git a/packages/mui-material/src/styles/adaptV4Theme.d.ts b/packages/mui-material/src/stylesDeprecated/adaptV4Theme.d.ts similarity index 73% rename from packages/mui-material/src/styles/adaptV4Theme.d.ts rename to packages/mui-material/src/stylesDeprecated/adaptV4Theme.d.ts index af04b5cadd8353..a99c6beb202849 100644 --- a/packages/mui-material/src/styles/adaptV4Theme.d.ts +++ b/packages/mui-material/src/stylesDeprecated/adaptV4Theme.d.ts @@ -1,14 +1,14 @@ import { BreakpointsOptions, ShapeOptions, SpacingOptions } from '@mui/system'; -import { MixinsOptions } from './createMixins'; -import { Palette, PaletteOptions } from './createPalette'; -import { TypographyVariantsOptions } from './createTypography'; -import { Shadows } from './shadows'; -import { TransitionsOptions } from './createTransitions'; -import { ZIndexOptions } from './zIndex'; +import { MixinsOptions } from '../styles/createMixins'; +import { Palette, PaletteOptions } from '../styles/createPalette'; +import { TypographyVariantsOptions } from '../styles/createTypography'; +import { Shadows } from '../styles/shadows'; +import { TransitionsOptions } from '../styles/createTransitions'; +import { ZIndexOptions } from '../styles/zIndex'; import { ComponentsOverrides } from './overrides'; import { ComponentsVariants } from './variants'; import { ComponentsProps } from './props'; -import { Theme } from './createTheme'; +import { Theme } from '../styles/createTheme'; export type Direction = 'ltr' | 'rtl'; diff --git a/packages/mui-material/src/styles/adaptV4Theme.js b/packages/mui-material/src/stylesDeprecated/adaptV4Theme.js similarity index 100% rename from packages/mui-material/src/styles/adaptV4Theme.js rename to packages/mui-material/src/stylesDeprecated/adaptV4Theme.js diff --git a/packages/mui-material/src/styles/adaptV4Theme.test.js b/packages/mui-material/src/stylesDeprecated/adaptV4Theme.test.js similarity index 100% rename from packages/mui-material/src/styles/adaptV4Theme.test.js rename to packages/mui-material/src/stylesDeprecated/adaptV4Theme.test.js diff --git a/packages/mui-material/src/styles/components.ts b/packages/mui-material/src/stylesDeprecated/components.ts similarity index 100% rename from packages/mui-material/src/styles/components.ts rename to packages/mui-material/src/stylesDeprecated/components.ts diff --git a/packages/mui-material/src/stylesDeprecated/index.ts b/packages/mui-material/src/stylesDeprecated/index.ts new file mode 100644 index 00000000000000..c5f62f68a15c8c --- /dev/null +++ b/packages/mui-material/src/stylesDeprecated/index.ts @@ -0,0 +1,6 @@ +export { default as adaptV4Theme } from './adaptV4Theme'; +export { DeprecatedThemeOptions } from './adaptV4Theme'; +export { ComponentsProps, ComponentsPropsList } from './props'; +export { ComponentsVariants } from './variants'; +export { ComponentsOverrides, ComponentNameToClassKey } from './overrides'; +export { Components } from './components'; diff --git a/packages/mui-material/src/styles/overrides.ts b/packages/mui-material/src/stylesDeprecated/overrides.ts similarity index 100% rename from packages/mui-material/src/styles/overrides.ts rename to packages/mui-material/src/stylesDeprecated/overrides.ts diff --git a/packages/mui-material/src/styles/props.ts b/packages/mui-material/src/stylesDeprecated/props.ts similarity index 100% rename from packages/mui-material/src/styles/props.ts rename to packages/mui-material/src/stylesDeprecated/props.ts diff --git a/packages/mui-material/src/styles/variants.ts b/packages/mui-material/src/stylesDeprecated/variants.ts similarity index 100% rename from packages/mui-material/src/styles/variants.ts rename to packages/mui-material/src/stylesDeprecated/variants.ts