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,10 @@
# @mui/styled-engine-sc
This package is a wrapper around the `styled-components` package implementing the interface of `@mui/styled-engine`.
It's designed for developers who would like to use `styled-components` as the main styled engine instead of `@emotion/styled`.
## Documentation
<!-- #host-reference -->
Visit [https://mui.com/material-ui/integrations/styled-components/](https://mui.com/material-ui/integrations/styled-components/) to view the full documentation.

View File

@@ -0,0 +1,62 @@
{
"name": "@mui/styled-engine-sc",
"version": "7.3.6",
"author": "MUI Team",
"description": "styled() API wrapper package for styled-components.",
"keywords": [
"react",
"react-component",
"mui",
"styled-components"
],
"repository": {
"type": "git",
"url": "git+https://github.com/mui/material-ui.git",
"directory": "packages/mui-styled-engine-sc"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/mui/material-ui/issues"
},
"homepage": "https://mui.com/material-ui/integrations/styled-components/",
"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/styled-engine-sc\"",
"typescript": "tsc -p tsconfig.json"
},
"dependencies": {
"@babel/runtime": "^7.28.4",
"@types/hoist-non-react-statics": "^3.3.7",
"csstype": "^3.2.3",
"hoist-non-react-statics": "^3.3.2",
"prop-types": "^15.8.1"
},
"devDependencies": {
"@mui/internal-test-utils": "workspace:^",
"@types/chai": "^5.2.3",
"@types/react": "^19.2.7",
"chai": "^6.0.1",
"react": "^19.2.1",
"styled-components": "^6.1.19"
},
"peerDependencies": {
"styled-components": "^6.0.0"
},
"sideEffects": false,
"publishConfig": {
"access": "public",
"directory": "build"
},
"engines": {
"node": ">=14.0.0"
},
"exports": {
".": "./src/index.js",
"./*": "./src/*/index.js"
}
}

View File

@@ -0,0 +1,11 @@
import * as React from 'react';
import { CSSObject, StyleFunction } from 'styled-components';
export interface GlobalStylesProps<Theme extends object = {}> {
defaultTheme?: object;
styles: string | CSSObject | StyleFunction<Theme>;
}
export default function Global<Theme extends object = {}>(
props: GlobalStylesProps<Theme>,
): React.JSX.Element;

View File

@@ -0,0 +1,28 @@
import PropTypes from 'prop-types';
import { createGlobalStyle } from 'styled-components';
function isEmpty(obj) {
return obj === undefined || obj === null || Object.keys(obj).length === 0;
}
const GlobalStyles = createGlobalStyle((props) => {
const { styles, defaultTheme = {} } = props;
if (typeof styles === 'function') {
return styles(isEmpty(props.theme) ? defaultTheme : props.theme);
}
return styles;
});
export default GlobalStyles;
GlobalStyles.propTypes = {
defaultTheme: PropTypes.object,
styles: PropTypes.oneOfType([
PropTypes.array,
PropTypes.string,
PropTypes.object,
PropTypes.func,
]),
};

View File

@@ -0,0 +1,40 @@
import * as React from 'react';
import {
GlobalStyles as SCGlobalStyles,
GlobalStylesProps as SCGlobalStylesProps,
} from '@mui/styled-engine-sc';
interface Theme {
colors: {
primary: string;
secondary: string;
};
}
const defaultTheme: Theme = {
colors: {
primary: '#f00',
secondary: '#ff00',
},
};
export interface GlobalStylesProps {
/**
* The styles you want to apply globally.
*/
styles: SCGlobalStylesProps<Theme>['styles'];
}
function GlobalStyles(props: GlobalStylesProps): React.JSX.Element {
return <SCGlobalStyles {...props} defaultTheme={defaultTheme} />;
}
function Test() {
<GlobalStyles
styles={(theme) => ({
color: theme.colors.primary,
// @ts-expect-error tertiary color doesn't exist
backgroundColor: theme.colors.tertiary,
})}
/>;
}

View File

@@ -0,0 +1,93 @@
import { expect } from 'chai';
import { createRenderer, isJsdom } from '@mui/internal-test-utils';
import { ThemeProvider } from 'styled-components';
import styled from '..';
import GlobalStyles from './GlobalStyles';
describe('GlobalStyles', () => {
const { render } = createRenderer();
it.skipIf(isJsdom())('should add global styles', function test() {
const { container } = render(
<div>
<GlobalStyles styles={`span { color: rgb(0, 0, 255); }`} />
<span>Blue text</span>
</div>,
);
expect(container.getElementsByTagName('span')[0]).toHaveComputedStyle({
color: 'rgb(0, 0, 255)',
});
});
it.skipIf(isJsdom())('should add global styles using JS syntax', function test() {
const { container } = render(
<div>
<GlobalStyles styles={{ span: { color: 'rgb(0, 0, 255)' } }} />
<span>Blue text</span>
</div>,
);
expect(container.getElementsByTagName('span')[0]).toHaveComputedStyle({
color: 'rgb(0, 0, 255)',
});
});
it.skipIf(isJsdom())('should add global styles using function', function test() {
const { container } = render(
<ThemeProvider theme={{ color: 'rgb(0, 0, 255)' }}>
<GlobalStyles styles={(theme) => ({ span: { color: theme.color } })} />
<span>Blue text</span>
</ThemeProvider>,
);
expect(container.getElementsByTagName('span')[0]).toHaveComputedStyle({
color: 'rgb(0, 0, 255)',
});
});
it('should not throw if no theme is available', () => {
expect(() =>
render(
<GlobalStyles
defaultTheme={{ color: 'rgb(0, 0, 255)' }}
styles={(theme) => ({ span: { color: theme.color } })}
/>,
),
).not.to.throw();
});
it.skipIf(isJsdom())('should give precedence to styled()', function test() {
const Span = styled('span')`
color: rgb(255, 0, 0);
`;
const { container } = render(
<div>
<GlobalStyles styles={`span { color: rgb(0, 0, 255); }`} />
<Span>Red text</Span>
</div>,
);
expect(container.getElementsByTagName('span')[0]).toHaveComputedStyle({
color: 'rgb(255, 0, 0)',
});
});
it.skipIf(isJsdom())('should give precedence to styled() using JS syntax', function test() {
const Span = styled('span')({
color: 'rgb(255, 0, 0)',
});
const { container } = render(
<div>
<GlobalStyles styles={{ span: { color: 'rgb(0, 0, 255)' } }} />
<Span>Red text</Span>
</div>,
);
expect(container.getElementsByTagName('span')[0]).toHaveComputedStyle({
color: 'rgb(255, 0, 0)',
});
});
});

View File

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

View File

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

View File

@@ -0,0 +1,8 @@
import * as React from 'react';
export interface StyledEngineProviderProps {
children?: React.ReactNode;
injectFirst?: boolean;
}
export default function StyledEngineProvider(props: StyledEngineProviderProps): React.JSX.Element;

View File

@@ -0,0 +1,29 @@
import PropTypes from 'prop-types';
export default function StyledEngineProvider(props) {
const { injectFirst, children } = props;
if (injectFirst && typeof window !== 'undefined') {
const head = document.head;
if (!head.querySelector('[data-styled="active"]')) {
const injectFirstNode = document.createElement('style');
injectFirstNode.setAttribute('data-styled', 'active');
head.insertBefore(injectFirstNode, head.firstChild);
}
}
return children;
}
StyledEngineProvider.propTypes = {
/**
* Your component tree.
*/
children: PropTypes.node,
/**
* By default, the styles are injected last in the <head> element of the page.
* As a result, they gain more specificity than any other style sheet.
* If you want to override MUI's styles, set this prop.
*/
injectFirst: PropTypes.bool,
};

View File

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

View File

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

View File

@@ -0,0 +1,408 @@
import * as React from 'react';
import * as CSS from 'csstype';
import * as hoistNonReactStatics from 'hoist-non-react-statics';
type WithOptionalTheme<P extends { theme?: T | undefined }, T> = OmitU<P, 'theme'> & {
theme?: T | undefined;
};
// Helper type operators
// Pick that distributes over union types
export type PickU<T, K extends keyof T> = T extends any ? { [P in K]: T[P] } : never;
export type OmitU<T, K extends keyof T> = T extends any ? PickU<T, Exclude<keyof T, K>> : never;
// Any prop that has a default prop becomes optional, but its type is unchanged
// Undeclared default props are augmented into the resulting allowable attributes
// If declared props have indexed properties, ignore default props entirely as keyof gets widened
// Wrap in an outer-level conditional type to allow distribution over props that are unions
type Defaultize<P, D> = P extends any
? string extends keyof P
? P
: PickU<P, Exclude<keyof P, keyof D>> &
Partial<PickU<P, Extract<keyof P, keyof D>>> &
Partial<PickU<D, Exclude<keyof D, keyof P>>>
: never;
export type IntrinsicElementsKeys = keyof React.JSX.IntrinsicElements;
type ReactDefaultizedProps<C, P> = C extends { defaultProps: infer D } ? Defaultize<P, D> : P;
type MakeAttrsOptional<
C extends string | React.ComponentType<any>,
O extends object,
A extends keyof P,
P = React.ComponentPropsWithRef<
C extends IntrinsicElementsKeys | React.ComponentType<any> ? C : never
>,
> =
// Distribute unions early to avoid quadratic expansion
P extends any ? OmitU<ReactDefaultizedProps<C, P> & O, A> & Partial<PickU<P & O, A>> : never;
export type StyledComponentProps<
// The Component from whose props are derived
C extends string | React.ComponentType<any>,
// The Theme from the current context
T extends object,
// The other props added by the template
O extends object,
// The props that are made optional by .attrs
A extends keyof any,
// The Component passed with "forwardedAs" prop
FAsC extends string | React.ComponentType<any> = C,
> =
// Distribute O if O is a union type
O extends object
? WithOptionalTheme<MakeAttrsOptional<C, O, A> & MakeAttrsOptional<FAsC, O, A>, T>
: never;
export interface ThemeProps<T> {
theme: T;
}
export type ThemedStyledProps<P, T> = P & ThemeProps<T>;
export interface Keyframes {
getName(): string;
}
export * from 'styled-components';
export { default } from 'styled-components';
export { default as StyledEngineProvider } from './StyledEngineProvider';
export { default as GlobalStyles } from './GlobalStyles';
export * from './GlobalStyles';
/**
* For internal usage in `@mui/system` package
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_mutateStyles(
tag: React.ElementType,
processor: (styles: any) => any,
): void;
// Not needed anymore, but fixes https://github.com/mui/material-ui/issues/44112
// TODO: Remove it in v7
// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_processStyles(
tag: React.ElementType,
processor: (styles: any) => any,
): void;
// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_serializeStyles<P>(styles: Interpolation<P>): object;
// These are the same as the ones in @mui/styled-engine
// CSS.PropertiesFallback are necessary so that we support spreading of the mixins. For example:
// '@font-face'?: Fontface | Fontface[]
export type CSSProperties = CSS.PropertiesFallback<number | string>;
export type CSSPropertiesWithMultiValues = {
[K in keyof CSSProperties]: CSSProperties[K] | Array<Extract<CSSProperties[K], string>>;
};
export type CSSPseudos = { [K in CSS.Pseudos]?: unknown | CSSObject };
export interface CSSOthersObject {
[propertiesName: string]: unknown | CSSInterpolation;
}
export type CSSPseudosForCSSObject = { [K in CSS.Pseudos]?: CSSObject };
export interface ArrayCSSInterpolation extends Array<CSSInterpolation> {}
export interface CSSOthersObjectForCSSObject {
[propertiesName: string]: CSSInterpolation;
}
// Omit variants as a key, because we have a special handling for it
export interface CSSObject
extends CSSPropertiesWithMultiValues,
CSSPseudos,
Omit<CSSOthersObject, 'variants'> {}
interface CSSObjectWithVariants<Props> extends Omit<CSSObject, 'variants'> {
variants: Array<{
props: Props | ((props: Props) => boolean);
style:
| CSSObject
| ((args: Props extends { theme: any } ? { theme: Props['theme'] } : any) => CSSObject);
}>;
}
export type FalseyValue = undefined | null | false;
export type Interpolation<P> =
| InterpolationValue
| CSSObjectWithVariants<P>
| InterpolationFunction<P>
| FlattenInterpolation<P>;
// cannot be made a self-referential interface, breaks WithPropNested
// see https://github.com/microsoft/TypeScript/issues/34796
export type FlattenInterpolation<P> = ReadonlyArray<Interpolation<P>>;
export type InterpolationValue =
| string
| number
| FalseyValue
| Keyframes
| StyledComponentInterpolation
| CSSObject;
export type SimpleInterpolation = InterpolationValue | FlattenSimpleInterpolation;
// adapter for compatibility with @mui/styled-engine
export type CSSInterpolation = SimpleInterpolation;
export type FlattenSimpleInterpolation = ReadonlyArray<SimpleInterpolation>;
export type InterpolationFunction<P> = (props: P) => Interpolation<P>;
// abuse Pick to strip the call signature from ForwardRefExoticComponent
type ForwardRefExoticBase<P> = PickU<
React.ForwardRefExoticComponent<P>,
keyof React.ForwardRefExoticComponent<any>
>;
type StyledComponentPropsWithAs<
C extends string | React.ComponentType<any>,
T extends object,
O extends object,
A extends keyof any,
AsC extends string | React.ComponentType<any> = C,
FAsC extends string | React.ComponentType<any> = C,
> = StyledComponentProps<C, T, O, A, FAsC> & {
as?: AsC | undefined;
forwardedAs?: FAsC | undefined;
};
export type StyledComponent<
C extends keyof React.JSX.IntrinsicElements | React.ComponentType<any>,
T extends object = {},
O extends object = {},
A extends keyof any = never,
> = // the "string" allows this to be used as an object key
// I really want to avoid this if possible but it's the only way to use nesting with object styles...
string &
StyledComponentBase<C, T, O, A> &
hoistNonReactStatics.NonReactStatics<C extends React.ComponentType<any> ? C : never>;
// any doesn't count as assignable to never in the extends clause, and we default A to never
export type AnyStyledComponent =
| StyledComponent<any, any, any, any>
| StyledComponent<any, any, any>
| React.FunctionComponent<any>
| React.ComponentType<any>;
export type StyledComponentInnerComponent<C extends AnyStyledComponent> =
C extends StyledComponent<infer I, any, any, any>
? I
: C extends StyledComponent<infer I, any, any>
? I
: C;
export type StyledComponentInnerOtherProps<C extends AnyStyledComponent> =
C extends StyledComponent<any, any, infer O, any>
? O
: C extends StyledComponent<any, any, infer O>
? O
: never;
export type StyledComponentInnerAttrs<C extends AnyStyledComponent> =
C extends StyledComponent<any, any, any, infer A> ? A : never;
export interface StyledComponentBase<
C extends string | React.ComponentType<any>,
T extends object,
O extends object = {},
A extends keyof any = never,
> extends ForwardRefExoticBase<StyledComponentProps<C, T, O, A>> {
// add our own fake call signature to implement the polymorphic 'as' prop
(
props: StyledComponentProps<C, T, O, A> & {
as?: never | undefined;
forwardedAs?: never | undefined;
},
): React.ReactElement<StyledComponentProps<C, T, O, A>>;
<
AsC extends string | React.ComponentType<any> = C,
FAsC extends string | React.ComponentType<any> = AsC,
>(
props: StyledComponentPropsWithAs<AsC, T, O, A, AsC, FAsC>,
): React.ReactElement<StyledComponentPropsWithAs<AsC, T, O, A, AsC, FAsC>>;
withComponent<WithC extends AnyStyledComponent>(
component: WithC,
): StyledComponent<
StyledComponentInnerComponent<WithC>,
T,
O & StyledComponentInnerOtherProps<WithC>,
A | StyledComponentInnerAttrs<WithC>
>;
withComponent<WithC extends keyof React.JSX.IntrinsicElements | React.ComponentType<any>>(
component: WithC,
): StyledComponent<WithC, T, O, A>;
}
// remove the call signature from StyledComponent so Interpolation can still infer InterpolationFunction
type StyledComponentInterpolation =
| Pick<StyledComponentBase<any, any, any, any>, keyof StyledComponentBase<any, any>>
| Pick<StyledComponentBase<any, any, any>, keyof StyledComponentBase<any, any>>;
// These are typings coming from styled-components
// They are adjusted to accept the extended options coming from mui
type AnyIfEmpty<T extends object> = keyof T extends never ? any : T;
type ThemedStyledComponentFactories<T extends object> = {
[TTag in keyof React.JSX.IntrinsicElements]: ThemedStyledFunctionBase<TTag, T>;
};
export type StyledComponentPropsWithRef<
C extends keyof React.JSX.IntrinsicElements | React.ComponentType<any>,
> = C extends AnyStyledComponent
? React.ComponentPropsWithRef<StyledComponentInnerComponent<C>>
: React.ComponentPropsWithRef<C>;
// Same as in styled-components, but copied here so that it would use the Interpolation & CSS typings from above
export interface ThemedStyledFunctionBase<
C extends keyof React.JSX.IntrinsicElements | React.ComponentType<any>,
T extends object,
O extends object = {},
A extends keyof any = never,
> {
(first: TemplateStringsArray): StyledComponent<C, T, O, A>;
(
first:
| TemplateStringsArray
| CSSObject
| InterpolationFunction<ThemedStyledProps<StyledComponentPropsWithRef<C> & O, T>>,
...other: Array<Interpolation<ThemedStyledProps<StyledComponentPropsWithRef<C> & O, T>>>
): StyledComponent<C, T, O, A>;
<U extends object>(
first:
| TemplateStringsArray
| CSSObject
| InterpolationFunction<ThemedStyledProps<StyledComponentPropsWithRef<C> & O & U, T>>,
...other: Array<Interpolation<ThemedStyledProps<StyledComponentPropsWithRef<C> & O & U, T>>>
): StyledComponent<C, T, O & U, A>;
}
// same as ThemedStyledFunction in styled-components, but without attrs, and withConfig
export interface ThemedStyledFunction<
C extends keyof React.JSX.IntrinsicElements | React.ComponentType<any>,
T extends object,
O extends object = {},
A extends keyof any = never,
> extends ThemedStyledFunctionBase<C, T, O, A> {}
export type CreateStyledComponent<
ComponentProps extends {},
SpecificComponentProps extends {} = {},
JSXProps extends {} = {},
T extends object = {},
> = ThemedStyledFunction<React.ComponentType<ComponentProps>, T, SpecificComponentProps & JSXProps>;
// Config to be used with withConfig
export interface StyledConfig<O extends object = {}> {
// TODO: Add all types from the original StyledComponentWrapperProperties
componentId?: string;
displayName?: string;
label?: string;
target?: string;
shouldForwardProp?:
| ((prop: keyof O, defaultValidatorFn: (prop: keyof O) => boolean) => boolean)
| undefined;
}
/** Same as StyledConfig but shouldForwardProp must be a type guard */
export interface FilteringStyledOptions<Props, ForwardedProps extends keyof Props = keyof Props> {
componentId?: string;
displayName?: string;
label?: string;
shouldForwardProp?(propName: PropertyKey): propName is ForwardedProps;
target?: string;
}
// same as ThemedBaseStyledInterface in styled-components, but with added options & common props for MUI components
export interface ThemedBaseStyledInterface<
MUIStyledCommonProps extends object,
MuiStyledOptions extends object,
Theme extends object,
> extends ThemedStyledComponentFactories<Theme> {
<
C extends React.ComponentClass<React.ComponentProps<C>>,
ForwardedProps extends keyof React.ComponentProps<C> = keyof React.ComponentProps<C>,
>(
component: C,
options: FilteringStyledOptions<React.ComponentProps<C>, ForwardedProps> & MuiStyledOptions,
): CreateStyledComponent<
Pick<PropsOf<C>, ForwardedProps> & MUIStyledCommonProps,
{},
{
ref?: React.Ref<InstanceType<C>>;
},
Theme
>;
<C extends React.ComponentClass<React.ComponentProps<C>>>(
component: C,
options?: StyledConfig<PropsOf<C> & MUIStyledCommonProps> & MuiStyledOptions,
): CreateStyledComponent<
PropsOf<C> & MUIStyledCommonProps,
{},
{
ref?: React.Ref<InstanceType<C>>;
},
Theme
>;
<
C extends React.JSXElementConstructor<React.ComponentProps<C>>,
ForwardedProps extends keyof React.ComponentProps<C> = keyof React.ComponentProps<C>,
>(
component: C,
options: FilteringStyledOptions<React.ComponentProps<C>, ForwardedProps> & MuiStyledOptions,
): CreateStyledComponent<Pick<PropsOf<C>, ForwardedProps> & MUIStyledCommonProps, {}, {}, Theme>;
<C extends React.JSXElementConstructor<React.ComponentProps<C>>>(
component: C,
options?: StyledConfig<PropsOf<C> & MUIStyledCommonProps> & MuiStyledOptions,
): CreateStyledComponent<PropsOf<C> & MUIStyledCommonProps, {}, {}, Theme>;
<
Tag extends keyof React.JSX.IntrinsicElements,
ForwardedProps extends
keyof React.JSX.IntrinsicElements[Tag] = keyof React.JSX.IntrinsicElements[Tag],
>(
tag: Tag,
options: FilteringStyledOptions<React.JSX.IntrinsicElements[Tag], ForwardedProps> &
MuiStyledOptions,
): CreateStyledComponent<
MUIStyledCommonProps,
Pick<React.JSX.IntrinsicElements[Tag], ForwardedProps>,
{},
Theme
>;
<Tag extends keyof React.JSX.IntrinsicElements>(
tag: Tag,
options?: StyledConfig<MUIStyledCommonProps> & MuiStyledOptions,
): CreateStyledComponent<MUIStyledCommonProps, React.JSX.IntrinsicElements[Tag], {}, Theme>;
}
export type CreateMUIStyled<
MUIStyledCommonProps extends object = {},
MuiStyledOptions extends object = {},
T extends object = {},
> = ThemedBaseStyledInterface<MUIStyledCommonProps, MuiStyledOptions, AnyIfEmpty<T>>;
export type PropsOf<
C extends keyof React.JSX.IntrinsicElements | React.JSXElementConstructor<any>,
> = React.JSX.LibraryManagedAttributes<C, React.ComponentProps<C>>;
export interface MUIStyledComponent<
ComponentProps extends {},
SpecificComponentProps extends {} = {},
JSXProps extends {} = {},
> extends React.FC<ComponentProps & SpecificComponentProps & JSXProps> {
withComponent<C extends React.ComponentClass<React.ComponentProps<C>>>(
component: C,
): MUIStyledComponent<ComponentProps & PropsOf<C>, {}, { ref?: React.Ref<InstanceType<C>> }>;
withComponent<C extends React.ComponentType<React.ComponentProps<C>>>(
component: C,
): MUIStyledComponent<ComponentProps & PropsOf<C>>;
withComponent<Tag extends keyof React.JSX.IntrinsicElements>(
tag: Tag,
): MUIStyledComponent<ComponentProps, React.JSX.IntrinsicElements[Tag]>;
}

View File

@@ -0,0 +1,65 @@
import scStyled from 'styled-components';
export default function styled(tag, options) {
let stylesFactory;
if (options) {
stylesFactory = scStyled(tag).withConfig({
displayName: options.label,
shouldForwardProp: options.shouldForwardProp,
});
} else {
stylesFactory = scStyled(tag);
}
if (process.env.NODE_ENV !== 'production') {
const fn = (...styles) => {
const component = typeof tag === 'string' ? `"${tag}"` : 'component';
if (styles.length === 0) {
console.error(
[
`MUI: Seems like you called \`styled(${component})()\` without a \`style\` argument.`,
'You must provide a `styles` argument: `styled("div")(styleYouForgotToPass)`.',
].join('\n'),
);
} else if (styles.some((style) => style === undefined)) {
console.error(
`MUI: the styled(${component})(...args) API requires all its args to be defined.`,
);
}
return stylesFactory(...styles);
};
fn.withConfig = stylesFactory.withConfig;
return fn;
}
return stylesFactory;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_mutateStyles(tag, processor) {
// Styled-components attaches an instance to `componentStyle`.
// https://github.com/styled-components/styled-components/blob/da8151762dcf72735ffba358173d4c097f6d5888/packages/styled-components/src/models/StyledComponent.ts#L257
//
// The instance contains `rules` (the styles)
// https://github.com/styled-components/styled-components/blob/da8151762dcf72735ffba358173d4c097f6d5888/packages/styled-components/src/models/ComponentStyle.ts#L23
if (tag.componentStyle) {
tag.componentStyle.rules = processor(tag.componentStyle.rules);
}
}
// Not needed anymore, but fixes https://github.com/mui/material-ui/issues/44112
// TODO: Remove it in v7
// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_processStyles(tag, processor) {
return internal_mutateStyles(tag, processor);
}
// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_serializeStyles(styles) {
return styles;
}
export { ThemeContext, keyframes, css } from 'styled-components';
export { default as StyledEngineProvider } from './StyledEngineProvider';
export { default as GlobalStyles } from './GlobalStyles';

View File

@@ -0,0 +1,46 @@
import { expect } from 'chai';
import { createRenderer, screen } from '@mui/internal-test-utils';
import styled from '@mui/styled-engine-sc';
describe('styled', () => {
const { render } = createRenderer();
it('should help debug wrong args', () => {
expect(() => {
expect(() => {
styled('span')();
// Error message changes between browsers.
// It's not relevant to the test anyway.
}).to.throw();
}).toErrorDev('MUI: Seems like you called `styled("span")()` without a `style` argument');
expect(() => {
expect(() => {
styled('span')(undefined, { color: 'red' });
// Error message changes between browsers.
// It's not relevant to the test anyway.
}).to.throw();
}).toErrorDev('MUI: the styled("span")(...args) API requires all its args to be defined');
});
it('should respect the options', () => {
const StyledComponent = styled('div', {
shouldForwardProp: (prop) => prop !== 'color',
label: 'TestComponent',
})({ color: 'red' });
render(<StyledComponent data-testid="component" color="blue" />);
expect(screen.getByTestId('component')).not.to.have.attribute('color');
expect(screen.getByTestId('component').className).to.match(/^TestComponent-/);
});
it("should not allow styled-components's APIs: .attrs", () => {
expect(typeof styled('span').attrs).to.equal('undefined');
});
// The babel-plugin-styled-components depends on the withConfig option to be defined
it("should allow styled-components's APIs: .withConfig", () => {
expect(typeof styled('span').withConfig).to.equal('function');
});
});

View File

@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"skipLibCheck": true
},
"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);

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 });