init project
Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
Scorecards supply-chain security / Scorecards analysis (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled

This commit is contained in:
how2ice
2025-12-12 14:26:25 +09:00
commit 005cf56baf
43188 changed files with 1079531 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
# @mui/private-theming
The React theme context to be shared between `@mui/styles` and `@mui/material`.

View File

@@ -0,0 +1,66 @@
{
"name": "@mui/private-theming",
"version": "7.3.6",
"author": "MUI Team",
"description": "Private - The React theme context to be shared between `@mui/styles` and `@mui/material`.",
"keywords": [
"react",
"react-component",
"mui",
"theme"
],
"repository": {
"type": "git",
"url": "git+https://github.com/mui/material-ui.git",
"directory": "packages/mui-private-theming"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/mui/material-ui/issues"
},
"homepage": "https://github.com/mui/material-ui/tree/master/packages/mui-private-theming",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"scripts": {
"build": "code-infra build --skipTsc",
"release": "pnpm build && pnpm publish",
"test": "pnpm --workspace-root test:unit --project \"*:@mui/private-theming\"",
"typescript": "tsc -p tsconfig.json"
},
"dependencies": {
"@babel/runtime": "^7.28.4",
"@mui/utils": "workspace:^",
"prop-types": "^15.8.1"
},
"devDependencies": {
"@mui/internal-test-utils": "workspace:^",
"@mui/types": "workspace:^",
"@types/chai": "^5.2.3",
"@types/react": "^19.2.7",
"chai": "^6.0.1",
"react": "^19.2.1"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
},
"sideEffects": false,
"publishConfig": {
"access": "public",
"directory": "build"
},
"engines": {
"node": ">=14.0.0"
},
"exports": {
".": "./src/index.js",
"./*": "./src/*/index.js"
}
}

View File

@@ -0,0 +1,9 @@
import { DefaultTheme } from '../defaultTheme';
export interface ThemeProviderProps<Theme = DefaultTheme> {
children?: React.ReactNode;
theme: Partial<Theme> | ((outerTheme: Theme) => Theme);
}
export default function ThemeProvider<T = DefaultTheme>(
props: ThemeProviderProps<T>,
): React.ReactElement<ThemeProviderProps<T>>;

View File

@@ -0,0 +1,83 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import exactProp from '@mui/utils/exactProp';
import ThemeContext from '../useTheme/ThemeContext';
import useTheme from '../useTheme';
import nested from './nested';
// To support composition of theme.
function mergeOuterLocalTheme(outerTheme, localTheme) {
if (typeof localTheme === 'function') {
const mergedTheme = localTheme(outerTheme);
if (process.env.NODE_ENV !== 'production') {
if (!mergedTheme) {
console.error(
[
'MUI: You should return an object from your theme function, i.e.',
'<ThemeProvider theme={() => ({})} />',
].join('\n'),
);
}
}
return mergedTheme;
}
return { ...outerTheme, ...localTheme };
}
/**
* This component takes a `theme` prop.
* It makes the `theme` available down the React tree thanks to React context.
* This component should preferably be used at **the root of your component tree**.
*/
function ThemeProvider(props) {
const { children, theme: localTheme } = props;
const outerTheme = useTheme();
if (process.env.NODE_ENV !== 'production') {
if (outerTheme === null && typeof localTheme === 'function') {
console.error(
[
'MUI: You are providing a theme function prop to the ThemeProvider component:',
'<ThemeProvider theme={outerTheme => outerTheme} />',
'',
'However, no outer theme is present.',
'Make sure a theme is already injected higher in the React tree ' +
'or provide a theme object.',
].join('\n'),
);
}
}
const theme = React.useMemo(() => {
const output =
outerTheme === null ? { ...localTheme } : mergeOuterLocalTheme(outerTheme, localTheme);
if (output != null) {
output[nested] = outerTheme !== null;
}
return output;
}, [localTheme, outerTheme]);
return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>;
}
ThemeProvider.propTypes = {
/**
* Your component tree.
*/
children: PropTypes.node,
/**
* A theme object. You can provide a function to extend the outer theme.
*/
theme: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired,
};
if (process.env.NODE_ENV !== 'production') {
ThemeProvider.propTypes = exactProp(ThemeProvider.propTypes);
}
export default ThemeProvider;

View File

@@ -0,0 +1,122 @@
import * as React from 'react';
import { expect } from 'chai';
import {
createRenderer,
RenderCounter,
strictModeDoubleLoggingSuppressed,
} from '@mui/internal-test-utils';
import useTheme from '../useTheme';
import ThemeProvider from './ThemeProvider';
describe('ThemeProvider', () => {
const { render } = createRenderer();
it('should provide the theme', () => {
const ref = React.createRef();
const text = () => ref.current.textContent;
function Test() {
const theme = useTheme();
return <span ref={ref}>{theme.foo}</span>;
}
render(
<ThemeProvider theme={{ foo: 'foo' }}>
<Test />
</ThemeProvider>,
);
expect(text()).to.equal('foo');
});
it('should merge the themes', () => {
const ref = React.createRef();
const text = () => ref.current.textContent;
function Test() {
const theme = useTheme();
return (
<span ref={ref}>
{theme.foo}
{theme.bar}
</span>
);
}
render(
<ThemeProvider theme={{ bar: 'bar' }}>
<ThemeProvider theme={{ foo: 'foo' }}>
<Test />
</ThemeProvider>
</ThemeProvider>,
);
expect(text()).to.equal('foobar');
});
it('should memoize the merged output', () => {
const ref = React.createRef();
const getRenderCountRef = React.createRef();
const text = () => ref.current.textContent;
function Test() {
const theme = useTheme();
return (
<RenderCounter ref={getRenderCountRef}>
<span ref={ref}>
{theme.foo}
{theme.bar}
</span>
</RenderCounter>
);
}
const outerTheme = { bar: 'bar' };
const innerTheme = { foo: 'foo' };
function Container() {
return (
<ThemeProvider theme={outerTheme}>
<ThemeProvider theme={innerTheme}>
<Test />
</ThemeProvider>
</ThemeProvider>
);
}
const { setProps } = render(<Container />);
expect(text()).to.equal('foobar');
setProps({});
expect(text()).to.equal('foobar');
expect(getRenderCountRef.current()).to.equal(2);
});
describe('warnings', () => {
it('should warn about missing provider', () => {
expect(() => {
render(
<ThemeProvider theme={(theme) => theme}>
<div />
</ThemeProvider>,
);
}).toErrorDev([
'However, no outer theme is present.',
!strictModeDoubleLoggingSuppressed && 'However, no outer theme is present.',
]);
});
it('should warn about wrong theme function', () => {
expect(() => {
render(
<ThemeProvider theme={{ bar: 'bar' }}>
<ThemeProvider theme={() => {}}>
<div />
</ThemeProvider>
,
</ThemeProvider>,
);
}).toErrorDev([
'MUI: You should return an object from your theme function',
!strictModeDoubleLoggingSuppressed &&
'MUI: You should return an object from your theme function',
]);
});
});
});

View File

@@ -0,0 +1,2 @@
export { default } from './ThemeProvider';
export * from './ThemeProvider';

View File

@@ -0,0 +1,2 @@
export { default } from './ThemeProvider';
export { default as unstable_nested } from './nested';

View File

@@ -0,0 +1,3 @@
const hasSymbol = typeof Symbol === 'function' && Symbol.for;
export default hasSymbol ? Symbol.for('mui.nested') : '__THEME_NESTED__';

View File

@@ -0,0 +1,5 @@
/**
* The default theme interface, augment this to avoid having to set the theme type everywhere.
* Our [TypeScript guide on theme customization](https://mui.com/material-ui/customization/theming/#custom-variables) explains in detail how you would add custom properties.
*/
export interface DefaultTheme {}

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,7 @@
export { default as ThemeProvider } from './ThemeProvider';
export * from './ThemeProvider';
export { default as useTheme } from './useTheme';
export * from './useTheme';
export * from './defaultTheme';

View File

@@ -0,0 +1,4 @@
export { default as ThemeProvider } from './ThemeProvider';
export * from './ThemeProvider';
export { default as useTheme } from './useTheme';

View File

@@ -0,0 +1,10 @@
'use client';
import * as React from 'react';
const ThemeContext = React.createContext(null);
if (process.env.NODE_ENV !== 'production') {
ThemeContext.displayName = 'ThemeContext';
}
export default ThemeContext;

View File

@@ -0,0 +1,2 @@
export { default } from './useTheme';
export * from './useTheme';

View File

@@ -0,0 +1 @@
export { default } from './useTheme';

View File

@@ -0,0 +1,3 @@
import { DefaultTheme } from '../defaultTheme';
export default function useTheme<T = DefaultTheme>(): T;

View File

@@ -0,0 +1,14 @@
import * as React from 'react';
import ThemeContext from './ThemeContext';
export default function useTheme() {
const theme = React.useContext(ThemeContext);
if (process.env.NODE_ENV !== 'production') {
// TODO: uncomment once we enable eslint-plugin-react-compiler eslint-disable-next-line react-compiler/react-compiler
// eslint-disable-next-line react-hooks/rules-of-hooks -- It's not required to run React.useDebugValue in production
React.useDebugValue(theme);
}
return theme;
}

View File

@@ -0,0 +1,26 @@
import * as React from 'react';
import { expect } from 'chai';
import { createRenderer } from '@mui/internal-test-utils';
import useTheme from './useTheme';
import ThemeProvider from '../ThemeProvider';
describe('useTheme', () => {
const { render } = createRenderer();
it('should use the theme', () => {
const ref = React.createRef();
const text = () => ref.current.textContent;
function Test() {
const theme = useTheme();
return <span ref={ref}>{theme.foo}</span>;
}
render(
<ThemeProvider theme={{ foo: 'foo' }}>
<Test />
</ThemeProvider>,
);
expect(text()).to.equal('foo');
});
});

View File

@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.json",
"include": ["src/**/*"]
}

View File

@@ -0,0 +1,4 @@
// eslint-disable-next-line import/no-relative-packages
import sharedConfig from '../../vitest.shared.mts';
export default sharedConfig(import.meta.url, { jsdom: true });