diff --git a/docs/src/pages/guides/typescript.md b/docs/src/pages/guides/typescript.md index b82f93e1ad433c..e761b99b693d19 100644 --- a/docs/src/pages/guides/typescript.md +++ b/docs/src/pages/guides/typescript.md @@ -120,26 +120,21 @@ And a custom theme factory with additional defaulted options: ```jsx import { default as createMuiTheme, ThemeOptions } from '@material-next/core/styles/createMuiTheme' -import { merge } from 'lodash' export default function createMyTheme(options: ThemeOptions) { - return createMuiTheme( - merge( - { - appDrawer: { - width: 225, - breakpoint: 'lg', - }, - }, - options, - ), - ) + return createMuiTheme({ + appDrawer: { + width: 225, + breakpoint: 'lg', + }, + ...options, + }) } ``` This could be used like: -```js +```jsx import createMyTheme from './styles/createMyTheme' const theme = createMyTheme({appDrawer: {breakpoint: 'md'}}) diff --git a/examples/create-react-app-with-typescript/tslint.json b/examples/create-react-app-with-typescript/tslint.json index 943daa43419f9e..839989989548ba 100644 --- a/examples/create-react-app-with-typescript/tslint.json +++ b/examples/create-react-app-with-typescript/tslint.json @@ -26,9 +26,13 @@ "max-line-length": [ true, 120 ], "member-ordering": [ true, - "public-before-private", - "static-before-instance", - "variables-before-functions" + { + "order":[ + "public-before-private", + "static-before-instance", + "variables-before-functions" + ] + } ], "no-any": false, "no-arg": true, diff --git a/src/Table/Table.d.ts b/src/Table/Table.d.ts index 213b32f885618e..adc976268d87a6 100644 --- a/src/Table/Table.d.ts +++ b/src/Table/Table.d.ts @@ -2,9 +2,13 @@ import * as React from 'react'; import { StandardProps } from '..'; export interface TableProps extends StandardProps< - React.TableHTMLAttributes, + TableBaseProps, TableClassKey -> {} +> { + component?: string | React.ComponentType; +} + +export type TableBaseProps = React.TableHTMLAttributes; export type TableClassKey = | 'root' diff --git a/src/Table/TableBody.d.ts b/src/Table/TableBody.d.ts index d7a6a2310d2033..b11960597a41a0 100644 --- a/src/Table/TableBody.d.ts +++ b/src/Table/TableBody.d.ts @@ -2,9 +2,13 @@ import * as React from 'react'; import { StandardProps } from '..'; export interface TableBodyProps extends StandardProps< - React.HTMLAttributes, + TableBodyBaseProps, TableBodyClassKey -> {} +> { + component?: string | React.ComponentType; +} + +export type TableBodyBaseProps = React.HTMLAttributes; export type TableBodyClassKey = | 'root' diff --git a/src/Table/TableCell.d.ts b/src/Table/TableCell.d.ts index 59c4c5ed3e53a4..48422bd9739005 100644 --- a/src/Table/TableCell.d.ts +++ b/src/Table/TableCell.d.ts @@ -10,13 +10,19 @@ import { StandardProps } from '..'; * here. */ export interface TableCellProps extends StandardProps< - React.ThHTMLAttributes & React.TdHTMLAttributes, + TableCellBaseProps, TableCellClassKey > { + component?: string | React.ComponentType; padding?: Padding; numeric?: boolean; } +export type TableCellBaseProps = + & React.ThHTMLAttributes + & React.TdHTMLAttributes + ; + export type Padding = | 'default' | 'checkbox' diff --git a/src/Table/TableFooter.d.ts b/src/Table/TableFooter.d.ts index 0d6e14489c5c9a..34ee5ffc013f01 100644 --- a/src/Table/TableFooter.d.ts +++ b/src/Table/TableFooter.d.ts @@ -2,9 +2,13 @@ import * as React from 'react'; import { StandardProps } from '..'; export interface TableFooterProps extends StandardProps< - React.HTMLAttributes, + TableFooterBaseProps, TableFooterClassKey -> {} +> { + component?: string | React.ComponentType; +} + +export type TableFooterBaseProps = React.HTMLAttributes; export type TableFooterClassKey = | 'root' diff --git a/src/Table/TableHead.d.ts b/src/Table/TableHead.d.ts index 481e09042e50c7..538d01d20f0328 100644 --- a/src/Table/TableHead.d.ts +++ b/src/Table/TableHead.d.ts @@ -2,9 +2,13 @@ import * as React from 'react'; import { StandardProps } from '..'; export interface TableHeadProps extends StandardProps< - React.HTMLAttributes, + TableHeadBaseProps, TableHeadClassKey -> {} +> { + component?: string | React.ComponentType; +} + +export type TableHeadBaseProps = React.HTMLAttributes; export type TableHeadClassKey = | 'root' diff --git a/src/Table/TablePagination.d.ts b/src/Table/TablePagination.d.ts index 12b29b2ebaf8ed..c027feeab28dac 100644 --- a/src/Table/TablePagination.d.ts +++ b/src/Table/TablePagination.d.ts @@ -10,9 +10,10 @@ export interface LabelDisplayedRowsArgs { } export interface TablePaginationProps extends StandardProps< - TableCellProps, + TablePaginationBaseProps, TablePaginationClassKey > { + component?: string | React.ComponentType; count: number; labelDisplayedRows?: (paginationInfo: LabelDisplayedRowsArgs) => React.ReactNode; labelRowsPerPage?: React.ReactNode; @@ -23,6 +24,8 @@ export interface TablePaginationProps extends StandardProps< rowsPerPageOptions?: number[]; } +export type TablePaginationBaseProps = TableCellProps; + export type TablePaginationClassKey = | TableCellClassKey | 'toolbar' diff --git a/src/Table/TableRow.d.ts b/src/Table/TableRow.d.ts index 126958ef99dc03..d2f2659a5d1545 100644 --- a/src/Table/TableRow.d.ts +++ b/src/Table/TableRow.d.ts @@ -2,13 +2,16 @@ import * as React from 'react'; import { StandardProps } from '..'; export interface TableRowProps extends StandardProps< - React.HTMLAttributes, + TableRowBaseProps, TableRowClassKey > { + component?: string | React.ComponentType; hover?: boolean; selected?: boolean; } +export type TableRowBaseProps = React.HTMLAttributes; + export type TableRowClassKey = | 'root' | 'head' diff --git a/src/index.d.ts b/src/index.d.ts index 961b43dec30a90..c61a5e6c208e70 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -48,6 +48,11 @@ type Diff = ( /** @internal */ export type Omit = Pick>; +/** @internal */ +export type DeepPartial = { + [P in keyof T]?: DeepPartial; +} + export namespace PropTypes { type Alignment = 'inherit' | 'left' | 'center' | 'right' | 'justify'; type Color = 'inherit' | 'primary' | 'accent' | 'default'; diff --git a/src/styles/createBreakpoints.d.ts b/src/styles/createBreakpoints.d.ts index 6895d4049ff857..0c8bd6aff5ebe0 100644 --- a/src/styles/createBreakpoints.d.ts +++ b/src/styles/createBreakpoints.d.ts @@ -2,12 +2,6 @@ export type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; export type BreakpointValues = { [key in Breakpoint]: number }; export const keys: Breakpoint[]; -export interface BreakpointsOptions { - values: BreakpointValues; - unit: string; - step: number; -} - export interface Breakpoints { keys: Breakpoint[]; values: BreakpointValues; @@ -18,6 +12,11 @@ export interface Breakpoints { width: (key: Breakpoint) => number; } +export type BreakpointsOptions = Partial<{ + unit: string; + step: number; +} & Breakpoints>; + export default function createBreakpoints( - options: Partial & Partial + options: BreakpointsOptions ): Breakpoints; diff --git a/src/styles/createMixins.d.ts b/src/styles/createMixins.d.ts index faa581f9f162bc..c36c1ec80045f1 100644 --- a/src/styles/createMixins.d.ts +++ b/src/styles/createMixins.d.ts @@ -5,10 +5,15 @@ import { StyleRules } from '../styles'; export interface Mixins { gutters: (styles: React.CSSProperties) => React.CSSProperties; toolbar: React.CSSProperties; + // ... use interface declaration merging to add custom mixins } -export default function createMixins( +export interface MixinsOptions extends Partial { + // ... use interface declaration merging to add custom mixin options +} + +export default function createMixins( breakpoints: Breakpoints, spacing: Spacing, - mixins: T -): Mixins & T; + mixins: MixinsOptions, +): Mixins; diff --git a/src/styles/createMuiTheme.d.ts b/src/styles/createMuiTheme.d.ts index 7361e8443d15bf..da62a4985b2a01 100644 --- a/src/styles/createMuiTheme.d.ts +++ b/src/styles/createMuiTheme.d.ts @@ -1,25 +1,25 @@ import { Breakpoints, BreakpointsOptions } from './createBreakpoints'; -import { Mixins } from './createMixins'; -import { Palette } from './createPalette'; +import { Mixins, MixinsOptions } from './createMixins'; +import { Palette, PaletteOptions } from './createPalette'; import { Shadows } from './shadows'; -import { Spacing } from './spacing'; -import { Transitions } from './transitions'; +import { Spacing, SpacingOptions } from './spacing'; +import { Transitions, TransitionsOptions } from './transitions'; import { Typography, TypographyOptions } from './createTypography'; -import { ZIndex } from './zIndex'; +import { ZIndex, ZIndexOptions } from './zIndex'; import { Overrides } from './overrides' export type Direction = 'ltr' | 'rtl'; export interface ThemeOptions { direction?: Direction; - palette?: Partial; + palette?: PaletteOptions; typography?: TypographyOptions | ((palette: Palette) => TypographyOptions); - mixins?: Partial; - breakpoints?: Partial & Partial; + mixins?: MixinsOptions; + breakpoints?: BreakpointsOptions; shadows?: Shadows; - transitions?: Partial; - spacing?: Partial; - zIndex?: Partial; + transitions?: TransitionsOptions; + spacing?: SpacingOptions; + zIndex?: ZIndexOptions; overrides?: Overrides; } diff --git a/src/styles/createPalette.d.ts b/src/styles/createPalette.d.ts index d4c1fd49a6ab78..d704a720e67ace 100644 --- a/src/styles/createPalette.d.ts +++ b/src/styles/createPalette.d.ts @@ -1,4 +1,4 @@ -import { Color, Contrast } from '..'; +import { Color, Contrast, DeepPartial } from '..'; import { CommonColors } from '../colors/common'; interface ShadeText { @@ -60,6 +60,8 @@ export interface Palette { getContrastText: (color: string) => string; } +export type PaletteOptions = DeepPartial; + export default function createPalette( - palette: Partial + palette: PaletteOptions ): Palette; diff --git a/src/styles/createTypography.d.ts b/src/styles/createTypography.d.ts index 1766b2de7fe9ff..92264dcbe1992f 100644 --- a/src/styles/createTypography.d.ts +++ b/src/styles/createTypography.d.ts @@ -1,5 +1,6 @@ import * as React from 'react'; import { Palette } from './createPalette'; +import { DeepPartial } from '..' export type TextStyle = | 'display1' @@ -36,7 +37,7 @@ export interface TypographyStyle { export type Typography = { [type in Style]: TypographyStyle } & FontStyle; -export type TypographyOptions = Partial & Partial; +export type TypographyOptions = DeepPartial; export default function createTypography( palette: Palette, diff --git a/src/styles/createTypography.spec.js b/src/styles/createTypography.spec.js index 549f3769a2248e..680d2811ec05db 100644 --- a/src/styles/createTypography.spec.js +++ b/src/styles/createTypography.spec.js @@ -34,4 +34,10 @@ describe('createTypography', () => { const typography = createTypography(palette, { htmlFontSize: 10 }); assert.strictEqual(typography.display4.fontSize, '11.2rem'); }); + + it('should create a typography with custom display4', () => { + const customFontSize = '18px'; + const typography = createTypography(palette, { display4: { fontSize: customFontSize } }); + assert.strictEqual(typography.display4.fontSize, customFontSize); + }); }); diff --git a/src/styles/spacing.d.ts b/src/styles/spacing.d.ts index 131ced2a889ad7..375f2971243657 100644 --- a/src/styles/spacing.d.ts +++ b/src/styles/spacing.d.ts @@ -1,5 +1,11 @@ +import { DeepPartial } from '../index'; + export interface Spacing { unit: number } -declare const spacing: Spacing -export default spacing + +export type SpacingOptions = DeepPartial; + +declare const spacing: Spacing; + +export default spacing; diff --git a/src/styles/transitions.d.ts b/src/styles/transitions.d.ts index 0071378c3f8b0d..03835bf9d67586 100644 --- a/src/styles/transitions.d.ts +++ b/src/styles/transitions.d.ts @@ -1,3 +1,5 @@ +import { DeepPartial } from '../index'; + export interface Easing { easeInOut: string; easeOut: string; @@ -29,4 +31,6 @@ export interface Transitions { getAutoHeightDuration(height: number): number; } +export type TransitionsOptions = DeepPartial; + export default Transitions; diff --git a/src/styles/withTheme.d.ts b/src/styles/withTheme.d.ts index fb4cf84da6a95d..081f0db0e0df31 100644 --- a/src/styles/withTheme.d.ts +++ b/src/styles/withTheme.d.ts @@ -4,7 +4,7 @@ export interface WithTheme { theme: Theme } -declare const withTheme:

() => ( +declare const withTheme: () =>

( component: React.ComponentType

) => React.ComponentClass

; diff --git a/src/styles/zIndex.d.ts b/src/styles/zIndex.d.ts index 0064babb1d17cc..8e381fe17c8bdc 100644 --- a/src/styles/zIndex.d.ts +++ b/src/styles/zIndex.d.ts @@ -1,3 +1,5 @@ +import { DeepPartial } from '../index'; + export interface ZIndex { mobileStepper: number; menu: number; @@ -11,5 +13,9 @@ export interface ZIndex { snackbar: number; tooltip: number; } -declare const zIndex: ZIndex + +export type ZIndexOptions = DeepPartial; + +declare const zIndex: ZIndex; + export default zIndex; diff --git a/test/typescript/styles.spec.tsx b/test/typescript/styles.spec.tsx index 7734804c93297c..a9fb6fe9c8aac1 100644 --- a/test/typescript/styles.spec.tsx +++ b/test/typescript/styles.spec.tsx @@ -11,6 +11,7 @@ import { import Button from '../../src/Button/Button'; import { StyleRulesCallback } from '../../src/styles/withStyles'; import { Contrast } from '../../src/index'; +import {WithTheme} from "../../src/styles/withTheme"; // Shared types for examples type ComponentClassNames = 'root'; @@ -71,6 +72,35 @@ const AnotherStyledSFC = withStyles({ // Overriding styles const theme = createMuiTheme({ + palette: { + type: 'dark', + common: { + white: '#ffffff', + }, + }, + typography: { + display4: { + fontSize: 24, + }, + fontSize: 18, + }, + mixins: { + toolbar: { + backgroundColor: 'red', + } + }, + breakpoints: { + step: 3, + }, + transitions: { + duration: { + short: 50, + }, + }, + spacing: {}, + zIndex: { + appBar: 42, + }, overrides: { MuiButton: { // Name of the styleSheet @@ -88,12 +118,6 @@ const theme = createMuiTheme({ }, }); -const customTheme = createMuiTheme({ - palette: { - type: 'dark' as Contrast, - }, -}); - function OverridesTheme() { return ( @@ -103,21 +127,25 @@ function OverridesTheme() { } // withTheme -const ThemedComponent: React.SFC<{ theme: Theme }> = ({ theme }) => ( -

{theme.spacing.unit}
+const ComponentWithTheme = withTheme()( + ({ theme }) => ( +
{theme.spacing.unit}
+ ) ); -const ComponentWithTheme = withTheme()(ThemedComponent); + + // withStyles + withTheme -interface AllTheProps { - theme: Theme; - classes: { root: string }; -} +type AllTheProps = WithTheme & WithStyles<'root'> -const AllTheComposition = withTheme()(withStyles(styles)(({ theme, classes }) => ( +const AllTheComposition = withTheme()( + withStyles(styles)( + ({ theme, classes }: AllTheProps) => (
{theme.palette.text.primary}
))); + + // Can't use withStyles effectively as a decorator in TypeScript // due to https://github.com/Microsoft/TypeScript/issues/4881 //@withStyles(styles)