Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[system] Add createTheme util #26490

Merged
merged 39 commits into from
Jun 4, 2021
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c2bec25
wip
mnajdova May 28, 2021
afa90cc
create theme
mnajdova May 28, 2021
18bc931
test
mnajdova May 28, 2021
814450a
revert propsToClassKey
mnajdova May 28, 2021
6bff878
prettier
mnajdova May 28, 2021
d3f2433
revert
mnajdova May 28, 2021
9d09740
removed console.log
mnajdova May 28, 2021
4da97e0
add typing from createTheme
mnajdova May 28, 2021
63dcc03
typings & lint
mnajdova May 28, 2021
8abb409
css typings
mnajdova May 28, 2021
7c096b1
Merge branch 'next' into feat/styled-to-system
mnajdova May 28, 2021
de26199
fix typings
mnajdova May 28, 2021
46828e7
Merge branch 'feat/styled-to-system' into feat/createTheme-system
mnajdova May 28, 2021
289706d
default theme
mnajdova May 28, 2021
97b30da
prettier
mnajdova May 28, 2021
b16287e
fix Netlify
oliviertassinari May 30, 2021
b888b87
changed comment
mnajdova May 31, 2021
a0490ad
fixes
mnajdova May 31, 2021
8b95461
remove JSXInEl
mnajdova May 31, 2021
f920b85
Merge branch 'feat/styled-to-system' into feat/createTheme-system
mnajdova May 31, 2021
16b2faf
Merge branch 'next' into feat/createTheme-system
mnajdova Jun 1, 2021
56d6094
fixes
mnajdova Jun 1, 2021
200b204
some fixes
mnajdova Jun 1, 2021
1122983
fixes
mnajdova Jun 1, 2021
973666e
tsconfig
mnajdova Jun 1, 2021
80d99e6
lab tsconfig
mnajdova Jun 1, 2021
2af0a19
add merge.d.ts
mnajdova Jun 1, 2021
df4fc40
tsconfig
mnajdova Jun 1, 2021
0963c55
styled.d.ts
mnajdova Jun 1, 2021
898e5e9
spacing.d.ts
mnajdova Jun 1, 2021
feff451
prettier
mnajdova Jun 1, 2021
d2fe7a0
Sebastian's review
mnajdova Jun 1, 2021
3c66c87
extend ThemeOptions & Theme, revert breakpoints augmentaiton
mnajdova Jun 2, 2021
cbbde13
Merge branch 'next' into feat/createTheme-system
mnajdova Jun 3, 2021
08053da
revert some changes
mnajdova Jun 3, 2021
ec1df00
fixes
mnajdova Jun 3, 2021
b8f0966
replace any with unknown
mnajdova Jun 3, 2021
849da33
fixes
mnajdova Jun 3, 2021
1b26150
fixes
mnajdova Jun 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/src/pages/customization/breakpoints/breakpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ If you are using TypeScript, you would also need to use [module augmentation](/g
<!-- Tested with packages/material-ui/test/typescript/breakpointsOverrides.augmentation.tsconfig.json -->

```ts
declare module '@material-ui/core/styles' {
declare module '@material-ui/system' {
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
interface BreakpointOverrides {
xs: false; // removes the `xs` breakpoint
sm: false;
Expand Down
21 changes: 21 additions & 0 deletions docs/src/pages/guides/migration-v4/migration-v4.md
Original file line number Diff line number Diff line change
Expand Up @@ -1810,6 +1810,27 @@ You can use the [`collapse-rename-collapsedheight` codemod](https://github.com/m

- This HOC was removed. There's an alternative using the `useMediaQuery` hook on [this page](/components/use-media-query/#migrating-from-withwidth).

#### Breakpoints overrides

If you are using TypeScript, and you were using [module augmentation](/guides/typescript/#customization-of-theme) for the theme to accept custom breakpoints values, you need to update the path to the `BreakpointsOverrides` interface.

```diff
+declare module '@material-ui/system' {
-declare module '@material-ui/core/styles' {
interface BreakpointOverrides {
xs: false; // removes the `xs` breakpoint
sm: false;
md: false;
lg: false;
xl: false;
mobile: true; // adds the `mobile` breakpoint
tablet: true;
laptop: true;
desktop: true;
}
}
```

### `@material-ui/types`

- Rename the exported `Omit` type in `@material-ui/types`. The module is now called `DistributiveOmit`. The change removes the confusion with the built-in `Omit` helper introduced in TypeScript v3.5. The built-in `Omit`, while similar, is non-distributive. This leads to differences when applied to union types. [See this StackOverflow answer for further details](https://stackoverflow.com/a/57103940/1009797).
Expand Down
5 changes: 4 additions & 1 deletion packages/material-ui-lab/tsconfig.build.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@
},
"include": ["src/**/*.ts*"],
"exclude": ["src/**/*.d.ts", "src/**/*.test.*", "./**/*.spec.*", "**/test-utils.tsx"],
"references": [{ "path": "../material-ui/tsconfig.build.json" }]
"references": [
{ "path": "../material-ui/tsconfig.build.json" },
{ "path": "../material-ui-system/tsconfig.build.json" }
]
}
3 changes: 1 addition & 2 deletions packages/material-ui-system/src/Box/Box.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { OverridableComponent, OverrideProps } from '@material-ui/types';
import { Theme } from '../createTheme';
import {
SxProps,
StandardCSSProperties,
Expand Down Expand Up @@ -170,8 +171,6 @@ export type SystemProps = {
} &
CustomSystemProps;

export interface Theme {}

export interface BoxTypeMap<P = {}, D extends React.ElementType = 'div'> {
props: P &
SystemProps & {
Expand Down
5 changes: 4 additions & 1 deletion packages/material-ui-system/src/createBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import clsx from 'clsx';
import styled, { ThemeContext } from '@material-ui/styled-engine';
import styleFunctionSx, { extendSxProp } from './styleFunctionSx';
import createTheme from './createTheme';

function isEmpty(obj) {
return Object.keys(obj).length === 0;
Expand All @@ -13,7 +14,9 @@ const useTheme = (defaultTheme) => {
return isEmpty(contextTheme) ? defaultTheme : contextTheme;
};

export default function createBox(defaultTheme = {}) {
export const systemDefaultTheme = createTheme();

export default function createBox(defaultTheme = systemDefaultTheme) {
const BoxRoot = styled('div')(styleFunctionSx);

const Box = React.forwardRef(function Box(inProps, ref) {
Expand Down
3 changes: 1 addition & 2 deletions packages/material-ui-system/src/createStyled.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import * as React from 'react';
import * as CSS from 'csstype';
import { SxProps } from './styleFunctionSx';

export interface DefaultTheme {}
import { Theme as DefaultTheme } from './createTheme';

export interface SerializedStyles {
name: string;
Expand Down
27 changes: 5 additions & 22 deletions packages/material-ui-system/src/createStyled.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import styledEngineStyled from '@material-ui/styled-engine';
import createTheme from './createTheme';
import styleFunctionSx from './styleFunctionSx';
import propsToClassKey from './propsToClassKey';

Expand Down Expand Up @@ -54,25 +55,7 @@ const variantsResolver = (props, styles, theme, name) => {
export const shouldForwardProp = (prop) =>
prop !== 'styleProps' && prop !== 'theme' && prop !== 'isRtl' && prop !== 'sx' && prop !== 'as';

export const systemDefaultTheme = {
breakpoints: {
values: {},
},
direction: 'ltr',
mixins: {},
components: {},
palette: {
mode: 'light',
},
shadows: {},
typography: {},
spacing: 8,
shape: {
borderRadius: 4,
},
transitions: {},
zIndex: {},
};
export const systemDefaultTheme = createTheme();

const lowercaseFirstLetter = (string) => {
return string.charAt(0).toLowerCase() + string.slice(1);
Expand All @@ -95,7 +78,7 @@ export default function createStyled(input = {}) {
...options
} = inputOptions;

// if skipVariantsResolver option is defined, take the value, otherwise, true for root and false for other slots
// if skipVariantsResolver option is defined, take the value, otherwise, true for root and false for other slots.
const skipVariantsResolver =
inputSkipVariantsResolver !== undefined
? inputSkipVariantsResolver
Expand Down Expand Up @@ -170,11 +153,11 @@ export default function createStyled(input = {}) {

if (Array.isArray(styleArg) && numOfCustomFnsApplied > 0) {
const placeholders = new Array(numOfCustomFnsApplied).fill('');
// If the type is array, than we need to add placeholders in the template for the overrides, variants and the sx styles
// If the type is array, than we need to add placeholders in the template for the overrides, variants and the sx styles.
transformedStyleArg = [...styleArg, ...placeholders];
transformedStyleArg.raw = [...styleArg.raw, ...placeholders];
} else if (typeof styleArg === 'function') {
// If the type is function, we need to define the default theme
// If the type is function, we need to define the default theme.
transformedStyleArg = ({ theme: themeInput, ...other }) =>
styleArg({ theme: isEmpty(themeInput) ? defaultTheme : themeInput, ...other });
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createTheme, experimentalStyled as styled } from '@material-ui/core/styles';
import { createTheme, styled } from '@material-ui/system';

{
const theme = createTheme({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from 'chai';
import createMixins from './createMixins';
import createTheme from './createTheme';
import createTheme from './index';

describe('createMixins', () => {
it('should be able add other mixins', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createUnarySpacing } from '@material-ui/system';
import { createUnarySpacing } from '../spacing';

export type SpacingOptions =
| number
Expand Down Expand Up @@ -33,7 +33,7 @@ export default function createSpacing(spacingInput: SpacingOptions = 8): Spacing
}

// Material Design layouts are visually balanced. Most measurements align to an 8dp grid, which aligns both spacing and the overall layout.
// Smaller components, such as icons and type, can align to a 4dp grid.
// Smaller components, such as icons, can align to a 4dp grid.
// https://material.io/design/layout/understanding-layout.html#usage
const transform = createUnarySpacing({
spacing: spacingInput,
Expand Down
40 changes: 40 additions & 0 deletions packages/material-ui-system/src/createTheme/createTheme.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Breakpoints, BreakpointsOptions } from './createBreakpoints';
import { Mixins, MixinsOptions } from './createMixins';
import { Shadows } from './shadows';
import { Shape, ShapeOptions } from './shape';
import { Spacing, SpacingOptions } from './createSpacing';
import { Transitions, TransitionsOptions } from './createTransitions';

export { Breakpoint, BreakpointOverrides } from './createBreakpoints';

export type Direction = 'ltr' | 'rtl';

export interface ThemeOptions {
shape?: ShapeOptions;
breakpoints?: BreakpointsOptions;
direction?: Direction;
mixins?: MixinsOptions;
palette?: Record<string, any>;
shadows?: Shadows;
spacing?: SpacingOptions;
transitions?: TransitionsOptions;
}
oliviertassinari marked this conversation as resolved.
Show resolved Hide resolved

export interface Theme {
shape: Shape;
breakpoints: Breakpoints;
direction: Direction;
mixins: Mixins;
palette: Record<string, any> & { mode: 'light' | 'dark' };
shadows: Shadows;
spacing: Spacing;
transitions: Transitions;
}

/**
* Generate a theme base on the options received.
* @param options Takes an incomplete theme object and adds the missing parts.
* @param args Deep merge the arguments with the about to be returned theme.
* @returns A complete, ready to use theme object.
*/
export default function createTheme(options?: ThemeOptions, ...args: object[]): Theme;
44 changes: 44 additions & 0 deletions packages/material-ui-system/src/createTheme/createTheme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { deepmerge } from '@material-ui/utils';
import createBreakpoints from './createBreakpoints';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these are moved from the @material-ui/core/styles.

import createMixins from './createMixins';
import shadows from './shadows';
import shape from './shape';
import createSpacing from './createSpacing';
import createTransitions from './createTransitions';

function createTheme(options = {}, ...args) {
const {
breakpoints: breakpointsInput = {},
mixins: mixinsInput = {},
palette: paletteInput = {},
spacing: spacingInput,
transitions: transitionsInput = {},
shape: shapeInput = {},
...other
} = options;

const breakpoints = createBreakpoints(breakpointsInput);
const spacing = createSpacing(spacingInput);

let muiTheme = deepmerge(
{
breakpoints,
direction: 'ltr',
mixins: createMixins(breakpoints, spacing, mixinsInput),
components: {}, // Inject component definitions.
palette: { mode: 'light', ...paletteInput },
// Don't use [...shadows] until you've verified its transpiled code is not invoking the iterator protocol.
shadows: shadows.slice(),
spacing,
shape: { ...shape, shapeInput },
transitions: createTransitions(transitionsInput),
},
other,
);

muiTheme = args.reduce((acc, argument) => deepmerge(acc, argument), muiTheme);

return muiTheme;
}

export default createTheme;
2 changes: 2 additions & 0 deletions packages/material-ui-system/src/createTheme/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './createTheme';
export * from './createTheme';
1 change: 1 addition & 0 deletions packages/material-ui-system/src/createTheme/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './createTheme';
94 changes: 28 additions & 66 deletions packages/material-ui-system/src/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import * as React from 'react';
import { CSSObject } from './createStyled';
import {
ComposedStyleFunction,
StyleFunction,
Expand All @@ -13,7 +11,6 @@ import {
positions,
shadows,
sizing,
spacing,
typography,
} from './Box';
// disable automatic export
Expand Down Expand Up @@ -82,69 +79,6 @@ export const sizeHeight: SimpleStyleFunction<'sizeHeight'>;
export const boxSizing: SimpleStyleFunction<'boxSizing'>;
export type SizingProps = PropsFor<typeof sizing>;

// spacing.js
Copy link
Member Author

@mnajdova mnajdova Jun 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to spacing.d.ts and style.d.ts

Copy link
Member

@oliviertassinari oliviertassinari Jun 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, we need to break down this file 😅, or even jump one step and migrate the modules to TS.

export type SpacingProps = PropsFor<typeof spacing>;
export function createUnarySpacing<Spacing>(theme: { spacing: Spacing }): Spacing extends number
? (abs: number | string) => number | number
: Spacing extends any[]
? <Index extends number>(abs: Index | string) => Spacing[Index] | string
: Spacing extends (...args: unknown[]) => unknown
? Spacing
: // warns in Dev
() => undefined;

export const margin: SimpleStyleFunction<
| 'm'
| 'mt'
| 'mr'
| 'mb'
| 'ml'
| 'mx'
| 'my'
| 'margin'
| 'marginTop'
| 'marginRight'
| 'marginBottom'
| 'marginLeft'
| 'marginX'
| 'marginY'
>;

export type MarginProps = PropsFor<typeof margin>;

export const padding: SimpleStyleFunction<
| 'p'
| 'pt'
| 'pr'
| 'pb'
| 'pl'
| 'px'
| 'py'
| 'padding'
| 'paddingTop'
| 'paddingRight'
| 'paddingBottom'
| 'paddingLeft'
| 'paddingX'
| 'paddingY'
>;

export type PaddingProps = PropsFor<typeof padding>;

// style.js
export interface StyleOptions<PropKey> {
cssProperty?: PropKey | keyof React.CSSProperties | false;
prop: PropKey;
/**
* dot access in `Theme`
*/
themeKey?: string;
transform?: (cssValue: unknown) => number | string | React.CSSProperties | CSSObject;
}
export function style<PropKey extends string, Theme extends object>(
options: StyleOptions<PropKey>,
): StyleFunction<{ [K in PropKey]?: unknown } & { theme: Theme }>;

// typography.js
export const typographyVariant: SimpleStyleFunction<'typography'>;
export const fontFamily: SimpleStyleFunction<'fontFamily'>;
Expand All @@ -166,6 +100,9 @@ export function unstable_getThemeValue(prop: string, value: any, theme: object):
*/
export type ResponsiveStyleValue<T> = T | Array<T | null> | { [key: string]: T | null };

export * from './style';
export * from './spacing';

export {
default as unstable_styleFunctionSx,
extendSxProp as unstable_extendSxProp,
Expand All @@ -183,3 +120,28 @@ export * from './createStyled';

export { default as styled } from './styled';
export * from './styled';

export { default as createTheme } from './createTheme';
export * from './createTheme';

export { default as createBreakpoints } from './createTheme/createBreakpoints';
export * from './createTheme/createBreakpoints';

export { Mixins, MixinsOptions } from './createTheme/createMixins';

export {
duration,
easing,
Duration,
Easing,
Transitions,
TransitionsOptions,
} from './createTheme/createTransitions';

export { SpacingOptions } from './createTheme/createSpacing';

export { default as themeShadows } from './createTheme/shadows';
export * from './createTheme/shadows';

export { default as shape } from './createTheme/shape';
export * from './createTheme/shape';
5 changes: 5 additions & 0 deletions packages/material-ui-system/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ export { default as createBox } from './createBox';
export { default as createStyled } from './createStyled';
export * from './createStyled';
export { default as styled } from './styled';
export { default as createTheme } from './createTheme';
export { default as createBreakpoints } from './createTheme/createBreakpoints';
export { duration, easing } from './createTheme/createTransitions';
export { default as themeShadows } from './createTheme/shadows';
export { default as shape } from './createTheme/shape';
Loading