Skip to content

Commit

Permalink
[system] Improve the createBox types (mui#35532)
Browse files Browse the repository at this point in the history
  • Loading branch information
mnajdova authored Jan 12, 2023
1 parent 9244703 commit 5d55067
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 53 deletions.
7 changes: 3 additions & 4 deletions packages/mui-joy/src/Box/Box.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { createBox } from '@mui/system';
import PropTypes from 'prop-types';
import { OverridableComponent } from '@mui/types';
import { unstable_ClassNameGenerator as ClassNameGenerator } from '../className';
import { BoxTypeMap } from './BoxProps';
import { Theme } from '../styles/types';
import defaultTheme from '../styles/defaultTheme';

const Box = createBox({
const Box = createBox<Theme>({
defaultTheme,
defaultClassName: 'JoyBox-root',
generateClassName: ClassNameGenerator.generate,
}) as OverridableComponent<BoxTypeMap>;
});

Box.propTypes /* remove-proptypes */ = {
// ----------------------------- Warning --------------------------------
Expand Down
22 changes: 2 additions & 20 deletions packages/mui-joy/src/Box/BoxProps.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,10 @@
import { OverrideProps } from '@mui/types';
import { SxProps, SystemProps } from '@mui/system';
import { BoxTypeMap } from '@mui/system';
import { Theme } from '../styles/types';

export type BoxSlot = 'root';

export interface BoxTypeMap<P = {}, D extends React.ElementType = 'div'> {
props: P &
SystemProps<Theme> & {
children?: React.ReactNode;
/**
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component?: React.ElementType;
ref?: React.Ref<unknown>;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
};
defaultComponent: D;
}

export type BoxProps<
D extends React.ElementType = BoxTypeMap['defaultComponent'],
P = {},
> = OverrideProps<BoxTypeMap<P, D>, D>;
> = OverrideProps<BoxTypeMap<P, D, Theme>, D>;
27 changes: 5 additions & 22 deletions packages/mui-material/src/Box/Box.d.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
import { SxProps, SystemProps } from '@mui/system';
import { OverridableComponent, OverrideProps } from '../OverridableComponent';
import { Theme } from '../styles';
import { createBox, BoxTypeMap } from '@mui/system';
import { OverrideProps } from '../OverridableComponent';
import { Theme as MaterialTheme } from '../styles';

export interface BoxTypeMap<P = {}, D extends React.ElementType = 'div'> {
props: P &
SystemProps<Theme> & {
children?: React.ReactNode;
/**
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component?: React.ElementType;
ref?: React.Ref<unknown>;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
};
defaultComponent: D;
}
/**
*
* Demos:
Expand All @@ -29,11 +12,11 @@ export interface BoxTypeMap<P = {}, D extends React.ElementType = 'div'> {
*
* - [Box API](https://mui.com/material-ui/api/box/)
*/
declare const Box: OverridableComponent<BoxTypeMap>;
declare const Box: ReturnType<typeof createBox<MaterialTheme>>;

export type BoxProps<
D extends React.ElementType = BoxTypeMap['defaultComponent'],
P = {},
> = OverrideProps<BoxTypeMap<P, D>, D>;
> = OverrideProps<BoxTypeMap<P, D, MaterialTheme>, D>;

export default Box;
11 changes: 11 additions & 0 deletions packages/mui-material/src/Box/Box.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import { Box as SystemBox, createBox } from '@mui/system';
import { expectType } from '@mui/types';
import { createTheme } from '@mui/material/styles';

function ThemeValuesCanBeSpread() {
<Box
Expand All @@ -21,3 +24,11 @@ function ThemeValuesCanBeSpread() {
})}
/>;
}

// Compatibility with Material UI's Box
const defaultTheme = createTheme({});
const CustomBox = createBox({ defaultTheme });
expectType<typeof Box, typeof CustomBox>(CustomBox);

// @ts-expect-error System's Box has different type than Material UI's Box
expectType<typeof SystemBox, typeof CustomBox>(CustomBox);
6 changes: 3 additions & 3 deletions packages/mui-system/src/Box/Box.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,9 @@ export type SystemProps<Theme extends object = {}> = {
| ((theme: Theme) => ResponsiveStyleValue<AllSystemCSSProperties[K]>);
};

export interface BoxTypeMap<P = {}, D extends React.ElementType = 'div'> {
export interface BoxTypeMap<P = {}, D extends React.ElementType = 'div', T extends object = Theme> {
props: P &
SystemProps<Theme> & {
SystemProps<T> & {
children?: React.ReactNode;
/**
* The component used for the root node.
Expand All @@ -183,7 +183,7 @@ export interface BoxTypeMap<P = {}, D extends React.ElementType = 'div'> {
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
sx?: SxProps<T>;
};
defaultComponent: D;
}
Expand Down
13 changes: 9 additions & 4 deletions packages/mui-system/src/createBox.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import Box from './Box';
import { OverridableComponent } from '@mui/types';
import { BoxTypeMap } from './Box';
import { Theme as SystemTheme } from './createTheme';

export default function createBox(options?: {
defaultTheme: object;
export default function createBox<
T extends object = SystemTheme,
AdditionalProps extends Record<string, unknown> = {},
>(options?: {
defaultTheme: T;
defaultClassName?: string;
generateClassName?: (componentName: string) => string;
}): typeof Box;
}): OverridableComponent<BoxTypeMap<AdditionalProps, 'div', T>>;
1 change: 1 addition & 0 deletions scripts/generateProptypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const useExternalPropsFromInputBase = [
*/
const useExternalDocumentation: Record<string, '*' | readonly string[]> = {
Button: ['disableRipple'],
Box: ['component', 'sx'],
// `classes` is always external since it is applied from a HOC
// In DialogContentText we pass it through
// Therefore it's considered "unused" in the actual component but we still want to document it.
Expand Down

0 comments on commit 5d55067

Please sign in to comment.