Completely updated React, fixed #11, (hopefully)

This commit is contained in:
2018-03-04 19:11:49 -05:00
parent 6e0afd6e2a
commit 34e5f5139a
13674 changed files with 333464 additions and 473223 deletions

View File

@@ -1,12 +1,19 @@
import { StyleSheet } from 'jss';
import * as React from 'react';
import { Theme } from './createMuiTheme';
import { StyleRules, StylesCreator } from './withStyles';
interface SheetManagerTheme {
refs: number;
sheet: StyleSheet<string>;
}
export interface MuiThemeProviderProps {
theme?: Theme<any>;
sheetsManager?: Object;
theme: Theme | ((outer: Theme | null) => Theme);
sheetsManager?: Map<StylesCreator, Map<Theme, SheetManagerTheme>>;
children: React.ReactNode;
}
declare const MuiThemeProvider: React.ComponentType<MuiThemeProviderProps>
declare const MuiThemeProvider: React.ComponentType<MuiThemeProviderProps>;
export default MuiThemeProvider
export default MuiThemeProvider;

View File

@@ -1,7 +1,7 @@
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
import _extends from 'babel-runtime/helpers/extends';
import React from 'react';
import PropTypes from 'prop-types';
import warning from 'warning';
import createBroadcast from 'brcast';
import themeListener, { CHANNEL } from './themeListener';
import exactProp from '../utils/exactProp';
@@ -12,7 +12,6 @@ import exactProp from '../utils/exactProp';
* This component should preferably be used at **the root of your component tree**.
*/
class MuiThemeProvider extends React.Component {
constructor(props, context) {
super(props, context);
@@ -26,12 +25,20 @@ class MuiThemeProvider extends React.Component {
}
getChildContext() {
const { sheetsManager, disableStylesGeneration } = this.props;
const muiThemeProviderOptions = this.context.muiThemeProviderOptions || {};
if (sheetsManager !== undefined) {
muiThemeProviderOptions.sheetsManager = sheetsManager;
}
if (disableStylesGeneration !== undefined) {
muiThemeProviderOptions.disableStylesGeneration = disableStylesGeneration;
}
return {
[CHANNEL]: this.broadcast,
muiThemeProviderOptions: {
sheetsManager: this.props.sheetsManager,
disableStylesGeneration: this.props.disableStylesGeneration
}
muiThemeProviderOptions
};
}
@@ -63,6 +70,7 @@ class MuiThemeProvider extends React.Component {
mergeOuterLocalTheme(localTheme) {
// To support composition of theme.
if (typeof localTheme === 'function') {
process.env.NODE_ENV !== "production" ? warning(this.outerTheme, ['Material-UI: you are providing a theme function property ' + 'to the MuiThemeProvider component:', '<MuiThemeProvider 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')) : void 0;
return localTheme(this.outerTheme);
}
@@ -78,11 +86,7 @@ class MuiThemeProvider extends React.Component {
}
}
MuiThemeProvider.defaultProps = {
disableStylesGeneration: false,
sheetsManager: null
};
MuiThemeProvider.propTypes = {
MuiThemeProvider.propTypes = process.env.NODE_ENV !== "production" ? {
/**
* You can only provide a single element with react@15, a node with react@16.
*/
@@ -106,22 +110,16 @@ MuiThemeProvider.propTypes = {
* A theme object.
*/
theme: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired
};
} : {};
MuiThemeProvider.propTypes = process.env.NODE_ENV !== "production" ? exactProp(MuiThemeProvider.propTypes, 'MuiThemeProvider') : {};
MuiThemeProvider.childContextTypes = _extends({}, themeListener.contextTypes, {
muiThemeProviderOptions: PropTypes.object
});
MuiThemeProvider.contextTypes = themeListener.contextTypes;
MuiThemeProvider.contextTypes = _extends({}, themeListener.contextTypes, {
muiThemeProviderOptions: PropTypes.object
});
// Add a wrapper component to generate some helper messages in the development
// environment.
// eslint-disable-next-line import/no-mutable-exports
let MuiThemeProviderWrapper = MuiThemeProvider;
if (process.env.NODE_ENV !== 'production') {
MuiThemeProviderWrapper = props => React.createElement(MuiThemeProvider, props);
MuiThemeProviderWrapper.propTypes = exactProp(MuiThemeProvider.propTypes, 'MuiThemeProvider');
}
export default MuiThemeProviderWrapper;
export default MuiThemeProvider;

View File

@@ -1,16 +1,13 @@
export type ColorFormat = 'rgb' | 'rgba' | 'hsl' | 'hsla';
export type ColorObject = {
export interface ColorObject {
type: ColorFormat;
color: [number, number, number] | [number, number, number, number];
};
values: [number, number, number] | [number, number, number, number];
}
export function convertColorToString(color: ColorObject): string;
export function recomposeColor(color: ColorObject): string;
export function convertHexToRGB(hex: string): string;
export function decomposeColor(color: string): ColorObject;
export function getContrastRatio(
foreground: string,
background: string
): number;
export function getContrastRatio(foreground: string, background: string): number;
export function getLuminance(color: string): number;
export function emphasize(color: string, coefficient?: number): string;
export function fade(color: string, value: number): string;

View File

@@ -1,6 +1,8 @@
// weak
/* eslint-disable no-use-before-define */
import warning from 'warning';
/**
* Returns a number whose value is limited to the given range.
*
@@ -9,7 +11,9 @@
* @param {number} max The upper boundary of the output range
* @returns {number} A number in the range [min, max]
*/
function clamp(value, min, max) {
function clamp(value, min = 0, max = 1) {
process.env.NODE_ENV !== "production" ? warning(value >= min && value <= max, `Material-UI: the value provided ${value} is out of range [${min}, ${max}].`) : void 0;
if (value < min) {
return min;
}
@@ -19,41 +23,6 @@ function clamp(value, min, max) {
return value;
}
/**
* Converts a color object with type and values to a string.
*
* @param {object} color - Decomposed color
* @param {string} color.type - One of, 'rgb', 'rgba', 'hsl', 'hsla'
* @param {array} color.values - [n,n,n] or [n,n,n,n]
* @returns {string} A CSS color string
*/
export function convertColorToString(color) {
const { type, values } = color;
if (type.indexOf('rgb') > -1) {
// Only convert the first 3 values to int (i.e. not alpha)
for (let i = 0; i < 3; i += 1) {
values[i] = parseInt(values[i], 10);
}
}
let colorString;
if (type.indexOf('hsl') > -1) {
colorString = `${color.type}(${values[0]}, ${values[1]}%, ${values[2]}%`;
} else {
colorString = `${color.type}(${values[0]}, ${values[1]}, ${values[2]}`;
}
if (values.length === 4) {
colorString += `, ${color.values[3]})`;
} else {
colorString += ')';
}
return colorString;
}
/**
* Converts a color from CSS hex format to CSS rgb format.
*
@@ -61,21 +30,16 @@ export function convertColorToString(color) {
* @returns {string} A CSS rgb color string
*/
export function convertHexToRGB(color) {
if (color.length === 4) {
let extendedColor = '#';
for (let i = 1; i < color.length; i += 1) {
extendedColor += color.charAt(i) + color.charAt(i);
}
color = extendedColor;
color = color.substr(1);
const re = new RegExp(`.{1,${color.length / 3}}`, 'g');
let colors = color.match(re);
if (colors && colors[0].length === 1) {
colors = colors.map(n => n + n);
}
const values = {
r: parseInt(color.substr(1, 2), 16),
g: parseInt(color.substr(3, 2), 16),
b: parseInt(color.substr(5, 2), 16)
};
return `rgb(${values.r}, ${values.g}, ${values.b})`;
return colors ? `rgb(${colors.map(n => parseInt(n, 16)).join(', ')})` : '';
}
/**
@@ -84,7 +48,7 @@ export function convertHexToRGB(color) {
* Note: Does not support rgb % values.
*
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
* @returns {{type: string, values: number[]}} A MUI color object
* @returns {object} - A MUI color object: {type: string, values: number[]}
*/
export function decomposeColor(color) {
if (color.charAt(0) === '#') {
@@ -99,28 +63,51 @@ export function decomposeColor(color) {
return { type, values };
}
/**
* Converts a color object with type and values to a string.
*
* @param {object} color - Decomposed color
* @param {string} color.type - One of: 'rgb', 'rgba', 'hsl', 'hsla'
* @param {array} color.values - [n,n,n] or [n,n,n,n]
* @returns {string} A CSS color string
*/
export function recomposeColor(color) {
const { type } = color;
let { values } = color;
if (type.indexOf('rgb') > -1) {
// Only convert the first 3 values to int (i.e. not alpha)
values = values.map((n, i) => i < 3 ? parseInt(n, 10) : n);
}
if (type.indexOf('hsl') > -1) {
values[1] = `${values[1]}%`;
values[2] = `${values[2]}%`;
}
return `${color.type}(${values.join(', ')})`;
}
/**
* Calculates the contrast ratio between two colors.
*
* Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
* Formula: https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
*
* @param {string} foreground - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
* @param {string} background - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
* @returns {number} A contrast ratio value in the range 0 - 21 with 2 digit precision.
* @returns {number} A contrast ratio value in the range 0 - 21.
*/
export function getContrastRatio(foreground, background) {
const lumA = getLuminance(foreground);
const lumB = getLuminance(background);
const contrastRatio = (Math.max(lumA, lumB) + 0.05) / (Math.min(lumA, lumB) + 0.05);
return Number(contrastRatio.toFixed(2)); // Truncate at two digits
return (Math.max(lumA, lumB) + 0.05) / (Math.min(lumA, lumB) + 0.05);
}
/**
* The relative brightness of any point in a color space,
* normalized to 0 for darkest black and 1 for lightest white.
*
* Formula: https://www.w3.org/WAI/GL/wiki/Relative_luminance
* Formula: https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
*
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
* @returns {number} The relative brightness of the color in the range 0 - 1
@@ -163,15 +150,19 @@ export function emphasize(color, coefficient = 0.15) {
* @returns {string} A CSS color string. Hex input values are returned as rgb
*/
export function fade(color, value) {
process.env.NODE_ENV !== "production" ? warning(color, `Material-UI: missing color argument in fade(${color}, ${value}).`) : void 0;
if (!color) return color;
color = decomposeColor(color);
value = clamp(value, 0, 1);
value = clamp(value);
if (color.type === 'rgb' || color.type === 'hsl') {
color.type += 'a';
}
color.values[3] = value;
return convertColorToString(color);
return recomposeColor(color);
}
/**
@@ -182,8 +173,12 @@ export function fade(color, value) {
* @returns {string} A CSS color string. Hex input values are returned as rgb
*/
export function darken(color, coefficient) {
process.env.NODE_ENV !== "production" ? warning(color, `Material-UI: missing color argument in darken(${color}, ${coefficient}).`) : void 0;
if (!color) return color;
color = decomposeColor(color);
coefficient = clamp(coefficient, 0, 1);
coefficient = clamp(coefficient);
if (color.type.indexOf('hsl') > -1) {
color.values[2] *= 1 - coefficient;
@@ -192,7 +187,7 @@ export function darken(color, coefficient) {
color.values[i] *= 1 - coefficient;
}
}
return convertColorToString(color);
return recomposeColor(color);
}
/**
@@ -203,8 +198,12 @@ export function darken(color, coefficient) {
* @returns {string} A CSS color string. Hex input values are returned as rgb
*/
export function lighten(color, coefficient) {
process.env.NODE_ENV !== "production" ? warning(color, `Material-UI: missing color argument in lighten(${color}, ${coefficient}).`) : void 0;
if (!color) return color;
color = decomposeColor(color);
coefficient = clamp(coefficient, 0, 1);
coefficient = clamp(coefficient);
if (color.type.indexOf('hsl') > -1) {
color.values[2] += (100 - color.values[2]) * coefficient;
@@ -214,5 +213,5 @@ export function lighten(color, coefficient) {
}
}
return convertColorToString(color);
return recomposeColor(color);
}

View File

@@ -2,22 +2,21 @@ 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: typeof keys;
keys: Breakpoint[];
values: BreakpointValues;
up: (key: Breakpoint | number) => string;
down: (key: Breakpoint | number) => string;
up: (key: Breakpoint | number) => string;
down: (key: Breakpoint | number) => string;
between: (start: Breakpoint, end: Breakpoint) => string;
only: (key: Breakpoint) => string;
width: (key: Breakpoint) => number;
}
export default function createBreakpoints(
options: Partial<BreakpointsOptions> & Partial<Breakpoints>
): Breakpoints;
export type BreakpointsOptions = Partial<
{
unit: string;
step: number;
} & Breakpoints
>;
export default function createBreakpoints(options: BreakpointsOptions): Breakpoints;

View File

@@ -1,18 +1,16 @@
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
import _extends from 'babel-runtime/helpers/extends';
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
// Sorted ASC by size. That's important.
// It can't be configured as it's used statically for propTypes.
export const keys = ['xs', 'sm', 'md', 'lg', 'xl'];
// Keep in mind that @media is inclusive by the CSS specification.
export default function createBreakpoints(breakpoints) {
const {
// The breakpoint **start** at this value.
// For instance with the first breakpoint xs: [xs, sm[.
values = {
xs: 360,
xs: 0,
sm: 600,
md: 960,
lg: 1280,
@@ -24,32 +22,34 @@ export default function createBreakpoints(breakpoints) {
other = _objectWithoutProperties(breakpoints, ['values', 'unit', 'step']);
function up(key) {
let value;
// min-width of xs starts at 0
if (key === 'xs') {
value = 0;
} else {
value = values[key] || key;
}
const value = typeof values[key] === 'number' ? values[key] : key;
return `@media (min-width:${value}${unit})`;
}
function down(key) {
const value = values[key] || key;
const endIndex = keys.indexOf(key) + 1;
const upperbound = values[keys[endIndex]];
if (endIndex === keys.length) {
// xl down applies to all sizes
return up('xs');
}
const value = typeof upperbound === 'number' && endIndex > 0 ? upperbound : key;
return `@media (max-width:${value - step / 100}${unit})`;
}
function between(start, end) {
const startIndex = keys.indexOf(start);
const endIndex = keys.indexOf(end);
return `@media (min-width:${values[keys[startIndex]]}${unit}) and ` + `(max-width:${values[keys[endIndex + 1]] - step / 100}${unit})`;
const endIndex = keys.indexOf(end) + 1;
if (endIndex === keys.length) {
return up(start);
}
return `@media (min-width:${values[start]}${unit}) and ` + `(max-width:${values[keys[endIndex]] - step / 100}${unit})`;
}
function only(key) {
const keyIndex = keys.indexOf(key);
if (keyIndex === keys.length - 1) {
return up(key);
}
return between(key, key);
}

View File

@@ -1,8 +1,10 @@
/**
* FIXME: `jss` TS typings are bad and incomplete ...
* So the following typigns are not really good.
*/
export default function createGenerateClassName(): (
rule: Object,
stylesheet?: Object
) => string;
import { GenerateClassName } from 'jss';
interface GenerateClassNameOptions {
dangerouslyUseGlobalCSS?: boolean;
productionPrefix?: string;
}
export default function createGenerateClassName(
options?: GenerateClassNameOptions,
): GenerateClassName<any>;

View File

@@ -1,18 +1,25 @@
import warning from 'warning';
let generatorCounter = 0;
// Returns a function which generates unique class names based on counters.
// When new generator function is created, rule counter is reset.
// We need to reset the rule counter for SSR for each request.
//
// It's an improved version of
// It's inspired by
// https://github.com/cssinjs/jss/blob/4e6a05dd3f7b6572fdd3ab216861d9e446c20331/src/utils/createGenerateClassName.js
export default function createGenerateClassName() {
export default function createGenerateClassName(options = {}) {
const { dangerouslyUseGlobalCSS = false, productionPrefix = 'jss' } = options;
const escapeRegex = /([[\].#*$><+~=|^:(),"'`\s])/g;
let ruleCounter = 0;
if (process.env.NODE_ENV === 'production' && typeof window !== 'undefined') {
// - HMR can lead to many class name generators being instantiated,
// so the warning is only triggered in production.
// - We expect a class name generator to be instantiated per new request on the server,
// so the warning is only triggered client side.
// - You can get away with having multiple class name generators
// by modifying the `productionPrefix`.
if (process.env.NODE_ENV === 'production' && typeof window !== 'undefined' && productionPrefix === 'jss') {
generatorCounter += 1;
if (generatorCounter > 2) {
@@ -21,21 +28,43 @@ export default function createGenerateClassName() {
}
}
return (rule, sheet) => {
return (rule, styleSheet) => {
ruleCounter += 1;
warning(ruleCounter < 1e10, ['Material-UI: you might have a memory leak.', 'The ruleCounter is not supposed to grow that much.'].join(''));
process.env.NODE_ENV !== "production" ? warning(ruleCounter < 1e10, ['Material-UI: you might have a memory leak.', 'The ruleCounter is not supposed to grow that much.'].join('')) : void 0;
if (process.env.NODE_ENV === 'production') {
return `c${ruleCounter}`;
// Code branch the whole block at the expense of more code.
if (dangerouslyUseGlobalCSS) {
if (styleSheet && styleSheet.options.classNamePrefix) {
let prefix = styleSheet.options.classNamePrefix;
// Sanitize the string as will be used to prefix the generated class name.
prefix = prefix.replace(escapeRegex, '-');
if (prefix.match(/^Mui/)) {
return `${prefix}-${rule.key}`;
}
if (process.env.NODE_ENV !== 'production') {
return `${prefix}-${rule.key}-${ruleCounter}`;
}
}
if (process.env.NODE_ENV === 'production') {
return `${productionPrefix}${ruleCounter}`;
}
return `${rule.key}-${ruleCounter}`;
}
if (sheet && sheet.options.meta) {
let meta = sheet.options.meta;
// Sanitize the string as will be used in development to prefix the generated
// class name.
meta = meta.replace(new RegExp(/[!"#$%&'()*+,./:; <=>?@[\\\]^`{|}~]/g), '-');
if (process.env.NODE_ENV === 'production') {
return `${productionPrefix}${ruleCounter}`;
}
return `${meta}-${rule.key}-${ruleCounter}`;
if (styleSheet && styleSheet.options.classNamePrefix) {
let prefix = styleSheet.options.classNamePrefix;
// Sanitize the string as will be used to prefix the generated class name.
prefix = prefix.replace(escapeRegex, '-');
return `${prefix}-${rule.key}-${ruleCounter}`;
}
return `${rule.key}-${ruleCounter}`;

View File

@@ -1,13 +1,19 @@
import { Breakpoints } from './createBreakpoints';
import { Spacing } from './spacing';
import { StyleRules } from '../styles';
export interface Mixins {
gutters: (styles: Object) => Object;
toolbar: Object;
gutters: (styles: React.CSSProperties) => React.CSSProperties;
toolbar: React.CSSProperties;
// ... use interface declaration merging to add custom mixins
}
export default function createMixins<T = {}>(
export interface MixinsOptions extends Partial<Mixins> {
// ... use interface declaration merging to add custom mixin options
}
export default function createMixins(
breakpoints: Breakpoints,
spacing: Spacing,
mixins: T
): Mixins & T;
mixins: MixinsOptions,
): Mixins;

View File

@@ -1,15 +1,16 @@
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
import _extends from 'babel-runtime/helpers/extends';
export default function createMixins(breakpoints, spacing, mixins) {
return _extends({
gutters: styles => {
styles.paddingLeft = spacing.unit * 2;
styles.paddingRight = spacing.unit * 2;
styles[breakpoints.up('sm')] = {
paddingLeft: spacing.unit * 3,
paddingRight: spacing.unit * 3
};
return styles;
return _extends({
paddingLeft: spacing.unit * 2,
paddingRight: spacing.unit * 2
}, styles, {
[breakpoints.up('sm')]: _extends({
paddingLeft: spacing.unit * 3,
paddingRight: spacing.unit * 3
}, styles[breakpoints.up('sm')])
});
},
toolbar: {
minHeight: 56,

View File

@@ -1,21 +1,30 @@
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 {
breakpoints?: Partial<BreakpointsOptions> & Partial<Breakpoints>;
mixins?: Partial<Mixins>;
palette?: Partial<Palette>;
direction?: Direction;
palette?: PaletteOptions;
typography?: TypographyOptions | ((palette: Palette) => TypographyOptions);
mixins?: MixinsOptions;
breakpoints?: BreakpointsOptions;
shadows?: Shadows;
transitions?: TransitionsOptions;
spacing?: SpacingOptions;
zIndex?: ZIndexOptions;
overrides?: Overrides;
}
export type Theme<T = {}> = {
direction: 'ltr' | 'rtl';
export interface Theme {
direction: Direction;
palette: Palette;
typography: Typography;
mixins: Mixins;
@@ -24,8 +33,7 @@ export type Theme<T = {}> = {
transitions: Transitions;
spacing: Spacing;
zIndex: ZIndex;
} & T;
overrides?: Overrides;
}
export default function createMuiTheme<T = {}>(
options?: ThemeOptions & T
): Theme<T>;
export default function createMuiTheme(options?: ThemeOptions): Theme;

View File

@@ -1,7 +1,5 @@
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
import _extends from 'babel-runtime/helpers/extends';
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import deepmerge from 'deepmerge'; // < 1kb payload overhead when lodash/merge is > 3kb.
import warning from 'warning';
import createTypography from './createTypography';
@@ -39,7 +37,7 @@ function createMuiTheme(options = {}) {
zIndex
}, other));
warning(muiTheme.shadows.length === 25, 'Material-UI: the shadows array provided to createMuiTheme should support 25 elevations.');
process.env.NODE_ENV !== "production" ? warning(muiTheme.shadows.length === 25, 'Material-UI: the shadows array provided to createMuiTheme should support 25 elevations.') : void 0;
return muiTheme;
}

View File

@@ -1,65 +1,84 @@
import { Color, Contrast } from '..';
import commonColors from '../colors/common';
import { Color, PaletteType } from '..';
import { CommonColors } from '../colors/common';
type ShadeText = {
interface TypeText {
primary: string;
secondary: string;
disabled: string;
hint: string;
icon: string;
divider: string;
lightDivider: string;
};
}
type ShadeInput = {
bottomLine: string;
helperText: string;
labelText: string;
inputText: string;
disabled: string;
};
type ShadeAction = {
interface TypeAction {
active: string;
hover: string;
selected: string;
disabled: string;
};
disabledBackground: string;
}
type ShadeBackground = {
interface TypeBackground {
default: string;
paper: string;
appBar: string;
contentFrame: string;
status: string;
};
}
export type Shade = {
text: ShadeText;
input: ShadeInput;
action: ShadeAction;
background: ShadeBackground;
};
export type PaletteColorOptions = SimplePaletteColorOptions | Partial<Color>;
export const light: Shade;
export const dark: Shade;
export interface SimplePaletteColorOptions {
light?: string;
main: string;
dark?: string;
contrastText?: string;
}
export type Palette = {
common: typeof commonColors;
type: Contrast;
primary: Color;
secondary: Color;
error: Color;
export interface PaletteColor {
light: string;
main: string;
dark: string;
contrastText: string;
}
export interface TypeObject {
text: TypeText;
action: TypeAction;
background: TypeBackground;
}
export const light: TypeObject;
export const dark: TypeObject;
export interface Palette {
common: CommonColors;
type: PaletteType;
contrastThreshold: number;
tonalOffset: number;
primary: PaletteColor;
secondary: PaletteColor;
error: PaletteColor;
grey: Color;
shades: {
dark: Shade;
light: Shade;
};
text: ShadeText;
input: ShadeInput;
action: ShadeAction;
background: ShadeBackground;
text: TypeText;
divider: string;
action: TypeAction;
background: TypeBackground;
getContrastText: (color: string) => string;
};
}
export default function createPalette(
palette: Partial<Palette>
): Palette;
type PartialTypeObject = { [P in keyof TypeObject]?: Partial<TypeObject[P]> };
type ColorPartial = Partial<Color>;
export interface PaletteOptions {
common?: Partial<CommonColors>;
type?: PaletteType;
primary?: PaletteColorOptions;
secondary?: PaletteColorOptions;
error?: PaletteColorOptions;
grey?: ColorPartial;
text?: Partial<TypeText>;
divider?: string;
action?: Partial<TypeAction>;
background?: Partial<TypeBackground>;
getContrastText?: (color: string) => string;
}
//export type PaletteOptions = DeepPartial<Palette>;
export default function createPalette(palette: PaletteOptions): Palette;

View File

@@ -1,5 +1,5 @@
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
import _extends from 'babel-runtime/helpers/extends';
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import warning from 'warning';
import deepmerge from 'deepmerge'; // < 1kb payload overhead when lodash/merge is > 3kb.
import indigo from '../colors/indigo';
@@ -7,117 +7,158 @@ import pink from '../colors/pink';
import grey from '../colors/grey';
import red from '../colors/red';
import common from '../colors/common';
import { getContrastRatio } from './colorManipulator';
import { getContrastRatio, darken, lighten } from './colorManipulator';
export const light = {
// The colors used to style the text.
text: {
// The most important text.
primary: 'rgba(0, 0, 0, 0.87)',
// Secondary text.
secondary: 'rgba(0, 0, 0, 0.54)',
// Disabled text have even lower visual prominence.
disabled: 'rgba(0, 0, 0, 0.38)',
hint: 'rgba(0, 0, 0, 0.38)',
icon: 'rgba(0, 0, 0, 0.38)',
divider: 'rgba(0, 0, 0, 0.12)',
lightDivider: 'rgba(0, 0, 0, 0.075)'
},
input: {
bottomLine: 'rgba(0, 0, 0, 0.42)',
helperText: 'rgba(0, 0, 0, 0.54)',
labelText: 'rgba(0, 0, 0, 0.54)',
inputText: 'rgba(0, 0, 0, 0.87)',
disabled: 'rgba(0, 0, 0, 0.42)'
},
action: {
active: 'rgba(0, 0, 0, 0.54)',
disabled: 'rgba(0, 0, 0, 0.26)'
// Text hints.
hint: 'rgba(0, 0, 0, 0.38)'
},
// The color used to divide different elements.
divider: 'rgba(0, 0, 0, 0.12)',
// The background colors used to style the surfaces.
// Consistency between these values is important.
background: {
default: grey[50],
paper: common.white,
appBar: grey[100],
contentFrame: grey[200]
default: grey[50]
},
// The colors used to style the action elements.
action: {
// The color of an active action like an icon button.
active: 'rgba(0, 0, 0, 0.54)',
// The color of an hovered action.
hover: 'rgba(0, 0, 0, 0.08)',
// The color of a selected action.
selected: 'rgba(0, 0, 0, 0.14)',
// The color of a disabled action.
disabled: 'rgba(0, 0, 0, 0.26)',
// The background color of a disabled action.
disabledBackground: 'rgba(0, 0, 0, 0.12)'
}
};
export const dark = {
text: {
primary: 'rgba(255, 255, 255, 1)',
primary: common.white,
secondary: 'rgba(255, 255, 255, 0.7)',
disabled: 'rgba(255, 255, 255, 0.5)',
hint: 'rgba(255, 255, 255, 0.5)',
icon: 'rgba(255, 255, 255, 0.5)',
divider: 'rgba(255, 255, 255, 0.12)',
lightDivider: 'rgba(255, 255, 255, 0.075)'
icon: 'rgba(255, 255, 255, 0.5)'
},
input: {
bottomLine: 'rgba(255, 255, 255, 0.7)',
helperText: 'rgba(255, 255, 255, 0.7)',
labelText: 'rgba(255, 255, 255, 0.7)',
inputText: 'rgba(255, 255, 255, 1)',
disabled: 'rgba(255, 255, 255, 0.5)'
divider: 'rgba(255, 255, 255, 0.12)',
background: {
paper: grey[800],
default: '#303030'
},
action: {
active: 'rgba(255, 255, 255, 1)',
disabled: 'rgba(255, 255, 255, 0.3)'
},
background: {
default: '#303030',
paper: grey[800],
appBar: grey[900],
contentFrame: grey[900]
active: common.white,
hover: 'rgba(255, 255, 255, 0.1)',
selected: 'rgba(255, 255, 255, 0.2)',
disabled: 'rgba(255, 255, 255, 0.3)',
disabledBackground: 'rgba(255, 255, 255, 0.12)'
}
};
function getContrastText(color) {
if (getContrastRatio(color, common.black) < 7) {
return dark.text.primary;
function addLightOrDark(intent, direction, shade, tonalOffset) {
if (!intent[direction]) {
if (intent.hasOwnProperty(shade)) {
intent[direction] = intent[shade];
} else if (direction === 'light') {
intent.light = lighten(intent.main, tonalOffset);
} else if (direction === 'dark') {
intent.dark = darken(intent.main, tonalOffset * 1.5);
}
}
return light.text.primary;
}
export default function createPalette(palette) {
const { primary = indigo, secondary = pink, error = red, type = 'light' } = palette,
other = _objectWithoutProperties(palette, ['primary', 'secondary', 'error', 'type']);
const shades = { dark, light };
const {
primary = {
light: indigo[300],
main: indigo[500],
dark: indigo[700]
},
secondary = {
light: pink.A200,
main: pink.A400,
dark: pink.A700
},
error = {
light: red[300],
main: red[500],
dark: red[700]
},
type = 'light',
contrastThreshold = 3,
tonalOffset = 0.2
} = palette,
other = _objectWithoutProperties(palette, ['primary', 'secondary', 'error', 'type', 'contrastThreshold', 'tonalOffset']);
warning(Boolean(shades[type]), `Material-UI: the palette type \`${type}\` is not supported.`);
function getContrastText(background) {
// Use the same logic as
// Bootstrap: https://github.com/twbs/bootstrap/blob/1d6e3710dd447de1a200f29e8fa521f8a0908f70/scss/_functions.scss#L59
// and material-components-web https://github.com/material-components/material-components-web/blob/ac46b8863c4dab9fc22c4c662dc6bd1b65dd652f/packages/mdc-theme/_functions.scss#L54
const contrastText = getContrastRatio(background, dark.text.primary) >= contrastThreshold ? dark.text.primary : light.text.primary;
const paletteOutput = deepmerge({
if (process.env.NODE_ENV !== 'production') {
const contrast = getContrastRatio(background, contrastText);
process.env.NODE_ENV !== "production" ? warning(contrast >= 3, [`Material-UI: the contrast ratio of ${contrast}:1 for ${contrastText} on ${background}`, 'falls below the WACG recommended absolute minimum contrast ratio of 3:1.', 'https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast'].join('\n')) : void 0;
}
return contrastText;
}
function augmentColor(color, mainShade, lightShade, darkShade) {
if (!color.main && color[mainShade]) {
color.main = color[mainShade];
}
addLightOrDark(color, 'light', lightShade, tonalOffset);
addLightOrDark(color, 'dark', darkShade, tonalOffset);
if (!color.contrastText) {
color.contrastText = getContrastText(color.main);
}
}
augmentColor(primary, 500, 300, 700);
augmentColor(secondary, 'A400', 'A200', 'A700');
augmentColor(error, 500, 300, 700);
const types = { dark, light };
process.env.NODE_ENV !== "production" ? warning(types[type], `Material-UI: the palette type \`${type}\` is not supported.`) : void 0;
const paletteOutput = deepmerge(_extends({
// A collection of common colors.
common,
// The palette type, can be light or dark.
type,
// The colors used to represent primary interface elements for a user.
primary,
// The colors used to represent secondary interface elements for a user.
secondary,
// The colors used to represent interface elements that the user should be made aware of.
error,
// The grey colors.
grey,
shades,
text: shades[type].text,
input: shades[type].input,
action: shades[type].action,
background: shades[type].background,
getContrastText
}, other, {
// Used by `getContrastText()` to maximize the contrast between the background and
// the text.
contrastThreshold,
// Take a background color and return the color of the text to maximize the contrast.
getContrastText,
// Used by the functions below to shift a color's luminance by approximately
// two indexes within its tonal palette.
// E.g., shift from Red 500 to Red 300 or Red 700.
tonalOffset
}, types[type]), other, {
clone: false // No need to clone deep
});
// Dev warnings
if (process.env.NODE_ENV !== 'production') {
const difference = (base, compare) => {
if (!compare) {
compare = {};
}
return Object.keys(base).filter(hue => !compare[hue]);
};
const paletteColorError = (name, base, compare) => {
const missing = difference(base, compare);
warning(missing.length === 0, [`Material-UI: ${name} color is missing the following hues: ${missing.join(',')}`, 'See the default colors, indigo, or pink, as exported from material-ui/colors.'].join('\n'));
};
paletteColorError('primary', indigo, paletteOutput.primary);
paletteColorError('secondary', pink, paletteOutput.secondary);
paletteColorError('error', red, paletteOutput.error);
paletteColorError('grey', red, paletteOutput.grey);
}
return paletteOutput;
}

View File

@@ -18,9 +18,9 @@ export type Style = TextStyle | 'button';
export interface FontStyle {
fontFamily: React.CSSProperties['fontFamily'];
fontSize: React.CSSProperties['fontSize'];
fontWeightLight: number | string;
fontWeightRegular: number | string;
fontWeightMedium: number | string;
fontWeightLight: React.CSSProperties['fontWeight'];
fontWeightRegular: React.CSSProperties['fontWeight'];
fontWeightMedium: React.CSSProperties['fontWeight'];
htmlFontSize?: number;
}
@@ -30,15 +30,21 @@ export interface TypographyStyle {
fontSize: React.CSSProperties['fontSize'];
fontWeight: React.CSSProperties['fontWeight'];
letterSpacing?: React.CSSProperties['letterSpacing'];
lineHeight: React.CSSProperties['lineHeight'];
lineHeight?: React.CSSProperties['lineHeight'];
textTransform?: React.CSSProperties['textTransform'];
}
export type Typography = { [type in Style]: TypographyStyle } & FontStyle;
export interface TypographyUtils {
pxToRem: (px: number) => string;
}
export type TypographyOptions = Partial<FontStyle> & Partial<Typography>;
export type Typography = Record<Style, TypographyStyle> & FontStyle & TypographyUtils;
export type TypographyOptions = Partial<Record<Style, Partial<TypographyStyle>> & FontStyle>;
//export type TypographyOptions = DeepPartial<Typography>;
export default function createTypography(
palette: Palette,
typography: TypographyOptions | ((palette: Palette) => TypographyOptions)
typography: TypographyOptions | ((palette: Palette) => TypographyOptions),
): Typography;

View File

@@ -1,5 +1,4 @@
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import deepmerge from 'deepmerge'; // < 1kb payload overhead when lodash/merge is > 3kb.
function round(value) {
@@ -23,6 +22,7 @@ export default function createTypography(palette, typography) {
return deepmerge({
pxToRem,
round,
fontFamily,
fontSize,
fontWeightLight,

View File

@@ -1,11 +1,13 @@
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
import _Object$keys from 'babel-runtime/core-js/object/keys';
import _extends from 'babel-runtime/helpers/extends';
import warning from 'warning';
import deepmerge from 'deepmerge'; // < 1kb payload overhead when lodash/merge is > 3kb.
function getStylesCreator(stylesOrCreator) {
const themingEnabled = typeof stylesOrCreator === 'function';
function create(theme, name) {
const styles = typeof stylesOrCreator === 'function' ? stylesOrCreator(theme) : stylesOrCreator;
const styles = themingEnabled ? stylesOrCreator(theme) : stylesOrCreator;
if (!theme.overrides || !name || !theme.overrides[name]) {
return styles;
@@ -14,10 +16,8 @@ function getStylesCreator(stylesOrCreator) {
const overrides = theme.overrides[name];
const stylesWithOverrides = _extends({}, styles);
Object.keys(overrides).forEach(key => {
warning(stylesWithOverrides[key], ['Material-UI: you are trying to override a style that does not exist.',
// $FlowFixMe - flow isn't smart enough
`Fix the \`${key}\` key of \`theme.overrides.${name}\`.`].join('\n'));
_Object$keys(overrides).forEach(key => {
process.env.NODE_ENV !== "production" ? warning(stylesWithOverrides[key], ['Material-UI: you are trying to override a style that does not exist.', `Fix the \`${key}\` key of \`theme.overrides.${name}\`.`].join('\n')) : void 0;
stylesWithOverrides[key] = deepmerge(stylesWithOverrides[key], overrides[key]);
});
@@ -26,10 +26,8 @@ function getStylesCreator(stylesOrCreator) {
return {
create,
options: {
index: undefined
},
themingEnabled: typeof stylesOrCreator === 'function'
options: {},
themingEnabled
};
}

View File

@@ -1,4 +1,12 @@
export { default as createGenerateClassName } from './createGenerateClassName';
export { default as createMuiTheme, Theme, Direction } from './createMuiTheme';
export { default as jssPreset } from './jssPreset';
export { default as MuiThemeProvider } from './MuiThemeProvider';
export { default as withStyles, WithStyles, StyleRules, StyleRulesCallback, StyledComponentProps } from './withStyles';
export { default as withTheme } from './withTheme';
export { default as createMuiTheme, Theme } from './createMuiTheme';
export {
default as withStyles,
WithStyles,
StyleRules,
StyleRulesCallback,
StyledComponentProps,
} from './withStyles';
export { default as withTheme, WithTheme } from './withTheme';

View File

@@ -1,4 +1,6 @@
export { default as createGenerateClassName } from './createGenerateClassName';
export { default as createMuiTheme } from './createMuiTheme';
export { default as jssPreset } from './jssPreset';
export { default as MuiThemeProvider } from './MuiThemeProvider';
export { default as withStyles } from './withStyles';
export { default as withTheme } from './withTheme';
export { default as createMuiTheme } from './createMuiTheme';
export { default as withTheme } from './withTheme';

View File

@@ -0,0 +1,3 @@
import { JSSOptions } from 'jss';
export default function jssPreset(): JSSOptions;

View File

@@ -0,0 +1,16 @@
import jssGlobal from 'jss-global';
import jssNested from 'jss-nested';
import jssCamelCase from 'jss-camel-case';
import jssDefaultUnit from 'jss-default-unit';
import jssVendorPrefixer from 'jss-vendor-prefixer';
import jssPropsSort from 'jss-props-sort';
// Subset of jss-preset-default with only the plugins the Material-UI
// components are using.
function jssPreset() {
return {
plugins: [jssGlobal(), jssNested(), jssCamelCase(), jssDefaultUnit(), jssVendorPrefixer(), jssPropsSort()]
};
}
export default jssPreset;

View File

@@ -0,0 +1,183 @@
import { AppBarClassKey } from '../AppBar/AppBar';
import { AvatarClassKey } from '../Avatar/Avatar';
import { BackdropClassKey } from '../Modal/Backdrop';
import { BadgeClassKey } from '../Badge/Badge';
import { BottomNavigationClassKey } from '../BottomNavigation/BottomNavigation';
import { BottomNavigationActionClassKey } from '../BottomNavigation/BottomNavigationAction';
import { ButtonClassKey } from '../Button/Button';
import { ButtonBaseClassKey } from '../ButtonBase/ButtonBase';
import { CardClassKey } from '../Card/Card';
import { CardActionsClassKey } from '../Card/CardActions';
import { CardContentClassKey } from '../Card/CardContent';
import { CardHeaderClassKey } from '../Card/CardHeader';
import { CardMediaClassKey } from '../Card/CardMedia';
import { CheckboxClassKey } from '../Checkbox/Checkbox';
import { ChipClassKey } from '../Chip/Chip';
import { CircularProgressClassKey } from '../Progress/CircularProgress';
import { CollapseClassKey } from '../transitions/Collapse';
import { DialogActionsClassKey } from '../Dialog/DialogActions';
import { DialogClassKey } from '../Dialog/Dialog';
import { DialogContentClassKey } from '../Dialog/DialogContent';
import { DialogContentTextClassKey } from '../Dialog/DialogContentText';
import { DialogTitleClassKey } from '../Dialog/DialogTitle';
import { DividerClassKey } from '../Divider/Divider';
import { DrawerClassKey } from '../Drawer/Drawer';
import { ExpansionPanelActionsClassKey } from '../ExpansionPanel/ExpansionPanelActions';
import { ExpansionPanelClassKey } from '../ExpansionPanel/ExpansionPanel';
import { ExpansionPanelDetailsClassKey } from '../ExpansionPanel/ExpansionPanelDetails';
import { ExpansionPanelSummaryClassKey } from '../ExpansionPanel/ExpansionPanelSummary';
import { FormControlClassKey } from '../Form/FormControl';
import { FormControlLabelClassKey } from '../Form/FormControlLabel';
import { FormGroupClassKey } from '../Form/FormGroup';
import { FormHelperTextClassKey } from '../Form/FormHelperText';
import { FormLabelClassKey } from '../Form/FormLabel';
import { GridClassKey } from '../Grid/Grid';
import { GridListClassKey } from '../GridList/GridList';
import { GridListTileBarClassKey } from '../GridList/GridListTileBar';
import { GridListTileClassKey } from '../GridList/GridListTile';
import { IconButtonClassKey } from '../IconButton/IconButton';
import { IconClassKey } from '../Icon/Icon';
import { InputAdornmentClassKey } from '../Input/InputAdornment';
import { InputClassKey } from '../Input/Input';
import { InputLabelClassKey } from '../Input/InputLabel';
import { LinearProgressClassKey } from '../Progress/LinearProgress';
import { ListClassKey } from '../List/List';
import { ListItemAvatarClassKey } from '../List/ListItemAvatar';
import { ListItemClassKey } from '../List/ListItem';
import { ListItemIconClassKey } from '../List/ListItemIcon';
import { ListItemSecondaryActionClassKey } from '../List/ListItemSecondaryAction';
import { ListItemTextClassKey } from '../List/ListItemText';
import { ListSubheaderClassKey } from '../List/ListSubheader';
import { MenuClassKey } from '../Menu/Menu';
import { MenuItemClassKey } from '../Menu/MenuItem';
import { MenuListClassKey } from '../Menu/MenuList';
import { MobileStepperClassKey } from '../MobileStepper/MobileStepper';
import { ModalClassKey } from '../Modal/Modal';
import { PaperClassKey } from '../Paper/Paper';
import { PopoverClassKey } from '../Popover/Popover';
import { RadioClassKey } from '../Radio/Radio';
import { RadioGroupClassKey } from '../Radio/RadioGroup';
import { SelectClassKey } from '../Select/Select';
import { SelectInputClassKey } from '../Select/SelectInput';
import { SnackbarClassKey } from '../Snackbar/Snackbar';
import { SnackbarContentClassKey } from '../Snackbar/SnackbarContent';
import { StepClasskey } from '../Stepper/Step';
import { StepButtonClasskey } from '../Stepper/StepButton';
import { StepConnectorClasskey } from '../Stepper/StepConnector';
import { StepContentClasskey } from '../Stepper/StepContent';
import { StepIconClasskey } from '../Stepper/StepIcon';
import { StepLabelClasskey } from '../Stepper/StepLabel';
import { StepperClasskey } from '../Stepper/Stepper';
import { StyleRules } from './withStyles';
import { SvgIconClassKey } from '../SvgIcon/SvgIcon';
import { SwitchBaseClassKey } from '../internal/SwitchBase';
import { SwitchClassKey } from '../Switch/Switch';
import { TabClassKey } from '../Tabs/Tab';
import { TabIndicatorClassKey } from '../Tabs/TabIndicator';
import { TableClassKey } from '../Table/Table';
import { TableCellClassKey } from '../Table/TableCell';
import { TablePaginationClassKey } from '../Table/TablePagination';
import { TableRowClassKey } from '../Table/TableRow';
import { TableSortLabelClassKey } from '../Table/TableSortLabel';
import { TabsClassKey } from '../Tabs/Tabs';
import { TabScrollButtonClassKey } from '../Tabs/TabScrollButton';
import { TextareaClassKey } from '../Input/Textarea';
import { ToolbarClassKey } from '../Toolbar/Toolbar';
import { TooltipClassKey } from '../Tooltip/Tooltip';
import { TouchRippleClassKey } from '../ButtonBase/TouchRipple';
import { TypographyClassKey } from '../Typography/Typography';
export type Overrides = {
[Name in keyof ComponentNameToClassKey]?: Partial<StyleRules<ComponentNameToClassKey[Name]>>
};
type ComponentNameToClassKey = {
MuiAppBar: AppBarClassKey;
MuiAvatar: AvatarClassKey;
MuiBackdrop: BackdropClassKey;
MuiBadge: BadgeClassKey;
MuiBottomNavigation: BottomNavigationClassKey;
MuiBottomNavigationAction: BottomNavigationActionClassKey;
MuiButton: ButtonClassKey;
MuiButtonBase: ButtonBaseClassKey;
// MuiCard: CardClassKey;
MuiCardActions: CardActionsClassKey;
MuiCardContent: CardContentClassKey;
MuiCardHeader: CardHeaderClassKey;
MuiCardMedia: CardMediaClassKey;
MuiCheckbox: CheckboxClassKey;
MuiChip: ChipClassKey;
MuiCircularProgress: CircularProgressClassKey;
MuiCollapse: CollapseClassKey;
MuiDialog: DialogClassKey;
MuiDialogActions: DialogActionsClassKey;
MuiDialogContent: DialogContentClassKey;
MuiDialogContentText: DialogContentTextClassKey;
MuiDialogTitle: DialogTitleClassKey;
MuiDivider: DividerClassKey;
MuiDrawer: DrawerClassKey;
MuiExpansionPanel: ExpansionPanelClassKey;
MuiExpansionPanelActions: ExpansionPanelActionsClassKey;
MuiExpansionPanelDetails: ExpansionPanelDetailsClassKey;
MuiExpansionPanelSummary: ExpansionPanelSummaryClassKey;
MuiFormControl: FormControlClassKey;
MuiFormControlLabel: FormControlLabelClassKey;
MuiFormGroup: FormGroupClassKey;
MuiFormHelperText: FormHelperTextClassKey;
MuiFormLabel: FormLabelClassKey;
MuiGrid: GridClassKey;
MuiGridList: GridListClassKey;
MuiGridListTile: GridListTileClassKey;
MuiGridListTileBar: GridListTileBarClassKey;
MuiIcon: IconClassKey;
MuiIconButton: IconButtonClassKey;
MuiInput: InputClassKey;
MuiInputAdornment: InputAdornmentClassKey;
MuiInputLabel: InputLabelClassKey;
MuiLinearProgress: LinearProgressClassKey;
MuiList: ListClassKey;
MuiListItem: ListItemClassKey;
MuiListItemAvatar: ListItemAvatarClassKey;
MuiListItemIcon: ListItemIconClassKey;
MuiListItemSecondaryAction: ListItemSecondaryActionClassKey;
MuiListItemText: ListItemTextClassKey;
MuiListSubheader: ListSubheaderClassKey;
MuiMenu: MenuClassKey;
MuiMenuItem: MenuItemClassKey;
// MuiMenuList: MenuListClassKey;
MuiMobileStepper: MobileStepperClassKey;
MuiModal: ModalClassKey;
MuiPaper: PaperClassKey;
MuiPopover: PopoverClassKey;
MuiRadio: RadioClassKey;
// MuiRadioGroup: RadioGroupClassKey;
MuiSelect: SelectClassKey;
// MuiSelectInput: SelectInputClassKey;
MuiSnackbar: SnackbarClassKey;
MuiSnackbarContent: SnackbarContentClassKey;
MuiStep: StepClasskey;
MuiStepButton: StepButtonClasskey;
MuiStepConnector: StepConnectorClasskey;
MuiStepContent: StepContentClasskey;
MuiStepIcon: StepIconClasskey;
MuiStepLabel: StepLabelClasskey;
MuiStepper: StepperClasskey;
MuiSvgIcon: SvgIconClassKey;
MuiSwitchBase: SwitchBaseClassKey;
MuiSwitch: SwitchClassKey;
MuiTab: TabClassKey;
MuiTabIndicator: TabIndicatorClassKey;
MuiTable: TableClassKey;
MuiTableCell: TableCellClassKey;
MuiTablePagination: TablePaginationClassKey;
MuiTableRow: TableRowClassKey;
MuiTableSortLabel: TableSortLabelClassKey;
MuiTabs: TabsClassKey;
MuiTabScrollButton: TabScrollButtonClassKey;
MuiTextarea: TextareaClassKey;
// MuiTextField: TextFieldClassKey;
MuiToolbar: ToolbarClassKey;
MuiTooltip: TooltipClassKey;
MuiTouchRipple: TouchRippleClassKey;
MuiTypography: TypographyClassKey;
};

View File

@@ -25,4 +25,5 @@ export type Shadows = [
string,
string
];
export default Shadows;
declare const shadows: Shadows;
export default shadows;

View File

@@ -1,4 +1,9 @@
export type Spacing = {
export interface Spacing {
unit: number;
};
export default Spacing;
}
export type SpacingOptions = Partial<Spacing>;
declare const spacing: Spacing;
export default spacing;

View File

@@ -1,15 +1,21 @@
// This is using the API from https://github.com/vesparny/brcast
interface MuiContext {
getState(): Object;
subscribe(callback: Function): Function;
interface Broadcast<S> {
setState(state: S): void;
getState(): S;
subscribe(callback: (state: S) => void): number;
unsubscribe(subscriptionId: number): void;
}
export interface ThemeListener {
contextTypes: {
'material-ui': object;
};
initial(context: Object): Object;
subscribe(context: Object, callback: Function): Function;
interface MuiContext<S> {
__THEMING__?: Broadcast<S>;
}
export default ThemeListener;
export interface ThemeListener<S = {}> {
initial(context: MuiContext<S>): S | null;
subscribe(context: MuiContext<S>, callback: (state: S) => void): number | null;
unsubscribe(context: MuiContext<S>, subscriptionId: number): void;
}
declare const themeListener: ThemeListener;
export default themeListener;

View File

@@ -24,9 +24,22 @@ export interface Transitions {
duration: Duration;
create(
props: string | string[],
options?: Partial<{ duration: number; easing: string; delay: number }>
options?: Partial<{ duration: number | string; easing: string; delay: number | string }>,
): string;
getAutoHeightDuration(height: number): number;
}
export default Transitions;
export interface TransitionsOptions {
easing?: Partial<Easing>;
duration?: Partial<Duration>;
create?: (
props: string | string[],
options?: Partial<{ duration: number | string; easing: string; delay: number | string }>,
) => string;
getAutoHeightDuration?: (height: number) => number;
}
//export type TransitionsOptions = DeepPartial<Transitions>;
declare const transitions: Transitions;
export default transitions;

View File

@@ -1,4 +1,6 @@
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
import _Object$keys from 'babel-runtime/core-js/object/keys';
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import _Number$isNaN from 'babel-runtime/core-js/number/is-nan';
/* eslint-disable no-param-reassign */
@@ -36,7 +38,7 @@ export const duration = {
export const formatMs = milliseconds => `${Math.round(milliseconds)}ms`;
export const isString = value => typeof value === 'string';
export const isNumber = value => !Number.isNaN(parseFloat(value));
export const isNumber = value => !_Number$isNaN(parseFloat(value));
/**
* @param {string|Array} props
@@ -57,13 +59,13 @@ export default {
} = options,
other = _objectWithoutProperties(options, ['duration', 'easing', 'delay']);
warning(isString(props) || Array.isArray(props), 'Material-UI: argument "props" must be a string or Array');
warning(isNumber(durationOption), `Material-UI: argument "duration" must be a number but found ${durationOption}`);
warning(isString(easingOption), 'Material-UI: argument "easing" must be a string');
warning(isNumber(delay), 'Material-UI: argument "delay" must be a string');
warning(Object.keys(other).length === 0, `Material-UI: unrecognized argument(s) [${Object.keys(other).join(',')}]`);
process.env.NODE_ENV !== "production" ? warning(isString(props) || Array.isArray(props), 'Material-UI: argument "props" must be a string or Array.') : void 0;
process.env.NODE_ENV !== "production" ? warning(isNumber(durationOption) || isString(durationOption), `Material-UI: argument "duration" must be a number or a string but found ${durationOption}.`) : void 0;
process.env.NODE_ENV !== "production" ? warning(isString(easingOption), 'Material-UI: argument "easing" must be a string.') : void 0;
process.env.NODE_ENV !== "production" ? warning(isNumber(delay) || isString(delay), 'Material-UI: argument "delay" must be a number or a string.') : void 0;
process.env.NODE_ENV !== "production" ? warning(_Object$keys(other).length === 0, `Material-UI: unrecognized argument(s) [${_Object$keys(other).join(',')}]`) : void 0;
return (Array.isArray(props) ? props : [props]).map(animatedProp => `${animatedProp} ${formatMs(durationOption)} ${easingOption} ${formatMs(delay)}`).join(',');
return (Array.isArray(props) ? props : [props]).map(animatedProp => `${animatedProp} ${typeof durationOption === 'string' ? durationOption : formatMs(durationOption)} ${easingOption} ${typeof delay === 'string' ? delay : formatMs(delay)}`).join(',');
},
getAutoHeightDuration(height) {
if (!height) {

View File

@@ -2,15 +2,23 @@ import * as React from 'react';
import { Theme } from './createMuiTheme';
/**
* This is basically the API of JSS. It defines a Map<string, CSS>,
* where
*
* - the `keys` are the class (names) that will be created
* - the `values` are objects that represent CSS rules (`React.CSSProperties`).
*/
export type StyleRules<ClassKey extends string = string> = Record<ClassKey, Partial<React.CSSProperties>>;
* This is basically the API of JSS. It defines a Map<string, CSS>,
* where
*
* - the `keys` are the class (names) that will be created
* - the `values` are objects that represent CSS rules (`React.CSSProperties`).
*/
export type StyleRules<ClassKey extends string = string> = Record<ClassKey, React.CSSProperties>;
export type StyleRulesCallback<ClassKey extends string = string> = (theme: Theme) => StyleRules<ClassKey>;
export type StyleRulesCallback<ClassKey extends string = string> = (
theme: Theme,
) => StyleRules<ClassKey>;
export interface StylesCreator {
create(theme: Theme, name: string): StyleRules;
options: { index: number };
themingEnabled: boolean;
}
export interface WithStylesOptions {
flip?: boolean;
@@ -21,8 +29,8 @@ export interface WithStylesOptions {
export type ClassNameMap<ClassKey extends string = string> = Record<ClassKey, string>;
export interface WithStyles<ClassKey extends string = string> {
classes: ClassNameMap<ClassKey>
theme?: Theme
classes: ClassNameMap<ClassKey>;
theme?: Theme;
}
export interface StyledComponentProps<ClassKey extends string = string> {
@@ -32,7 +40,7 @@ export interface StyledComponentProps<ClassKey extends string = string> {
export default function withStyles<ClassKey extends string>(
style: StyleRules<ClassKey> | StyleRulesCallback<ClassKey>,
options?: WithStylesOptions
options?: WithStylesOptions,
): <P>(
component: React.ComponentType<P & WithStyles<ClassKey>>
component: React.ComponentType<P & WithStyles<ClassKey>>,
) => React.ComponentType<P & StyledComponentProps<ClassKey>>;

View File

@@ -1,27 +1,25 @@
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
// weak
import _Object$keys from 'babel-runtime/core-js/object/keys';
import _extends from 'babel-runtime/helpers/extends';
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import _Map from 'babel-runtime/core-js/map';
import _Number$MIN_SAFE_INTEGER from 'babel-runtime/core-js/number/min-safe-integer';
import React from 'react';
import PropTypes from 'prop-types';
import warning from 'warning';
import hoistNonReactStatics from 'hoist-non-react-statics';
import wrapDisplayName from 'recompose/wrapDisplayName';
import getDisplayName from 'recompose/getDisplayName';
import wrapDisplayName from 'recompose/wrapDisplayName';
import contextTypes from 'react-jss/lib/contextTypes';
import { create } from 'jss';
import preset from 'jss-preset-default';
import * as ns from 'react-jss/lib/ns';
import jssPreset from './jssPreset';
import createMuiTheme from './createMuiTheme';
import themeListener from './themeListener';
import createGenerateClassName from './createGenerateClassName';
import getStylesCreator from './getStylesCreator';
// New JSS instance.
const jss = create(preset());
const jss = create(jssPreset());
// Use a singleton or the provided one by the context.
const generateClassName = createGenerateClassName();
@@ -34,9 +32,9 @@ const generateClassName = createGenerateClassName();
// specificity, because of the source order.
// So our solution is to render sheets them in the reverse order child->sheet, so
// that parent has a higher specificity.
let indexCounter = Number.MIN_SAFE_INTEGER;
let indexCounter = _Number$MIN_SAFE_INTEGER;
export const sheetsManager = new Map();
export const sheetsManager = new _Map();
// We use the same empty object to ref count the styles that don't need a theme object.
const noopTheme = {};
@@ -53,43 +51,35 @@ function getDefaultTheme() {
return defaultTheme;
}
// Note, theme is conditionally injected, but flow is static analysis so we need to include it.
// Link a style sheet with a component.
// It does not modify the component passed to it;
// instead, it returns a new component, with a `classes` property.
const withStyles = (stylesOrCreator, options = {}) => Component => {
const { withTheme = false, flip, name } = options,
const { withTheme = false, flip = null, name } = options,
styleSheetOptions = _objectWithoutProperties(options, ['withTheme', 'flip', 'name']);
const stylesCreator = getStylesCreator(stylesOrCreator);
const listenToTheme = stylesCreator.themingEnabled || withTheme || typeof name === 'string';
if (stylesCreator.options.index === undefined) {
indexCounter += 1;
stylesCreator.options.index = indexCounter;
}
indexCounter += 1;
stylesCreator.options.index = indexCounter;
warning(indexCounter < 0, ['Material-UI: you might have a memory leak.', 'The indexCounter is not supposed to grow that much.'].join(' '));
class Style extends React.Component {
process.env.NODE_ENV !== "production" ? warning(indexCounter < 0, ['Material-UI: you might have a memory leak.', 'The indexCounter is not supposed to grow that much.'].join(' ')) : void 0;
class WithStyles extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {};
this.unsubscribeId = null;
this.jss = null;
this.sheetsManager = sheetsManager;
this.disableStylesGeneration = false;
this.jss = null;
this.sheetOptions = null;
this.sheetsManager = sheetsManager;
this.stylesCreatorSaved = null;
this.theme = null;
this.sheetOptions = null;
this.theme = null;
const { muiThemeProviderOptions } = this.context;
this.unsubscribeId = null;
this.jss = this.context[ns.jss] || jss;
const { muiThemeProviderOptions } = this.context;
if (muiThemeProviderOptions) {
if (muiThemeProviderOptions.sheetsManager) {
this.sheetsManager = muiThemeProviderOptions.sheetsManager;
@@ -105,16 +95,10 @@ const withStyles = (stylesOrCreator, options = {}) => Component => {
this.sheetOptions = _extends({
generateClassName
}, this.context[ns.sheetOptions]);
// We use || as it's lazy evaluated.
// We use || as the function call is lazy evaluated.
this.theme = listenToTheme ? themeListener.initial(context) || getDefaultTheme() : noopTheme;
}
// Exposed for test purposes.
// Exposed for tests purposes
componentWillMount() {
this.attach(this.theme);
}
@@ -165,7 +149,7 @@ const withStyles = (stylesOrCreator, options = {}) => Component => {
let sheetManager = this.sheetsManager.get(stylesCreatorSaved);
if (!sheetManager) {
sheetManager = new Map();
sheetManager = new _Map();
this.sheetsManager.set(stylesCreatorSaved, sheetManager);
}
@@ -181,14 +165,15 @@ const withStyles = (stylesOrCreator, options = {}) => Component => {
if (sheetManagerTheme.refs === 0) {
const styles = stylesCreatorSaved.create(theme, name);
let meta;
let meta = name;
if (process.env.NODE_ENV !== 'production') {
meta = name || getDisplayName(Component);
if (process.env.NODE_ENV !== 'production' && !meta) {
meta = getDisplayName(Component);
}
const sheet = this.jss.createStyleSheet(styles, _extends({
meta,
classNamePrefix: meta,
flip: typeof flip === 'boolean' ? flip : theme.direction === 'rtl',
link: false
}, this.sheetOptions, stylesCreatorSaved.options, {
@@ -243,10 +228,10 @@ const withStyles = (stylesOrCreator, options = {}) => Component => {
}
if (classesProp) {
classes = _extends({}, renderedClasses, Object.keys(classesProp).reduce((accumulator, key) => {
warning(renderedClasses[key] || this.disableStylesGeneration, [`Material-UI: the key \`${key}\` ` + `provided to the classes property is not implemented in ${getDisplayName(Component)}.`, `You can only override one of the following: ${Object.keys(renderedClasses).join(',')}`].join('\n'));
classes = _extends({}, renderedClasses, _Object$keys(classesProp).reduce((accumulator, key) => {
process.env.NODE_ENV !== "production" ? warning(renderedClasses[key] || this.disableStylesGeneration, [`Material-UI: the key \`${key}\` ` + `provided to the classes property is not implemented in ${getDisplayName(Component)}.`, `You can only override one of the following: ${_Object$keys(renderedClasses).join(',')}`].join('\n')) : void 0;
warning(!classesProp[key] || typeof classesProp[key] === 'string', [`Material-UI: the key \`${key}\` ` + `provided to the classes property is not valid for ${getDisplayName(Component)}.`, `You need to provide a non empty string instead of: ${classesProp[key]}.`].join('\n'));
process.env.NODE_ENV !== "production" ? warning(!classesProp[key] || typeof classesProp[key] === 'string', [`Material-UI: the key \`${key}\` ` + `provided to the classes property is not valid for ${getDisplayName(Component)}.`, `You need to provide a non empty string instead of: ${classesProp[key]}.`].join('\n')) : void 0;
if (classesProp[key]) {
accumulator[key] = `${renderedClasses[key]} ${classesProp[key]}`;
@@ -270,20 +255,34 @@ const withStyles = (stylesOrCreator, options = {}) => Component => {
}
}
Style.contextTypes = _extends({
WithStyles.propTypes = process.env.NODE_ENV !== "production" ? {
/**
* Useful to extend the style applied to components.
*/
classes: PropTypes.object,
/**
* Use that property to pass a ref callback to the decorated component.
*/
innerRef: PropTypes.func
} : {};
WithStyles.contextTypes = _extends({
muiThemeProviderOptions: PropTypes.object
}, contextTypes, listenToTheme ? themeListener.contextTypes : {});
Style.Naked = Component;
hoistNonReactStatics(Style, Component);
// Higher specificity
Style.options = options;
if (process.env.NODE_ENV !== 'production') {
Style.displayName = wrapDisplayName(Component, 'withStyles');
WithStyles.displayName = wrapDisplayName(Component, 'WithStyles');
}
return Style;
hoistNonReactStatics(WithStyles, Component);
if (process.env.NODE_ENV !== 'production') {
// Exposed for test purposes.
WithStyles.Naked = Component;
WithStyles.options = options;
}
return WithStyles;
};
export default withStyles;

View File

@@ -1,5 +1,11 @@
import { Theme } from './createMuiTheme';
export default function withTheme<P = {}, T extends Theme = Theme>():
(component: React.ComponentType<P & { theme: T }>
) => React.ComponentClass<P>;
export interface WithTheme {
theme: Theme;
}
declare const withTheme: () => <P>(
component: React.ComponentType<P & WithTheme>,
) => React.ComponentClass<P>;
export default withTheme;

View File

@@ -1,11 +1,7 @@
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
// weak
// flow sanity check (DO NOT DELETE) https://flow.org/try/#0JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wG4AoUSWOGATzCTgG84BhXSAOyS5gBUGTAL5xsuAkXQwy5OQHp5cALSq16jZuVwdccorgB3YDAAW-U0hBMAEgHk25JAA9qWAK5cMwCFyMnzS2sAHgAFHDAAZwAuFmEAPgAKcl12Tl9eGFiOcAy+QUZg1jMrJFi7ACMAKyQMOFEAMjhwiCj4gBpyAEps9J58oTCIyPiWOR00ABsUSMi4AHUAi1K4FxheABM55GkAOhzuTKHWyPaWWiCyuEqauoSx1KIuDaQoRK6H1LgiGHcoP2CBzy8GYuzBZmAkV2YGGohK1gAvMwIVDIjAUOtdvCkKJ5PEKKlhAT6ilvkhfv8FktLuRhAolFpGUy1PolMYzMtrHAAKqRFAAcyQ5CmMzmAEFVs51s9tsQYPs+kdipdytVavBGiwULEuO4QBVXmcKjq9QaoPdmHS0L40XBOUgNkD+vAEf4OZdEmKuhQDPMmBtfPh4DwHbQIHAwKK4MA-AADbGx1YAN14Fwg7n5pjgsYAsnQnZlE0QAI7uYBEOYmXbkYL2x2KvhwFBIgCMogqSIATLj4vSVMyB6lWW7TIsNmY4PZHC43LQhHAAEJSADWkBjLoIzki+DgAB8CJEQDv9-gQBtjwRJvyL-hnJNZOR6IwqePTC0onBXcxSTGTMAUJMY5mAA-LES6oKuEDrp0OjGK+oGLiua58J0dJOK40AeF4MA+H47KjsAr7vJ8mCeN4virFwpgoF4SDHFEsRAW+wxJKSqQFnwvS5M6BR0cwcFmGBSFQShcBgrs76RAkMFwD0aTcZkvH0SMYxsXAIqzFSZhMZK0pbIgcoKgpfDKaM35fGSzyvMR5kWepNogr+OEAUxZwCaYoiuii0LDGpjzkn8AIcSC4neTCJyiO5SL4Ie+A9sShIJSSak-IFWkEa+xJEuMZIUn4vDUbRFBoQYA5leow7uHygrCtMmkLrpmyynswVFO5QkQchMBnNqcC6vqhrGn1pqvBapJPC8bwfLZEwOSw7meRckI+ScKUBZSwQbMASZwHipJ0lac1MQ6wWfiOTHvIkC7esOfpwAGXBBn1SChjA4aRppMbZu5iZICmfhmOmmbZnmwVFkgpblkglbyjWx31sZ8DNswbZwB2zDdrt+JAA
import _extends from 'babel-runtime/helpers/extends';
import React from 'react';
import hoistNonReactStatics from 'hoist-non-react-statics';
import wrapDisplayName from 'recompose/wrapDisplayName';
import createMuiTheme from './createMuiTheme';
import themeListener from './themeListener';
@@ -23,20 +19,16 @@ function getDefaultTheme() {
// Provide the theme object as a property to the input component.
const withTheme = () => Component => {
class WithTheme extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {};
this.unsubscribeId = null;
this.state = {
// We use || as it's lazy evaluated.
// We use || as the function call is lazy evaluated.
theme: themeListener.initial(context) || getDefaultTheme()
};
}
// Exposed for test purposes.
componentDidMount() {
this.unsubscribeId = themeListener.subscribe(this.context, theme => {
this.setState({ theme });
@@ -55,8 +47,18 @@ const withTheme = () => Component => {
}
WithTheme.contextTypes = themeListener.contextTypes;
WithTheme.displayName = wrapDisplayName(Component, 'withTheme');
WithTheme.Naked = Component;
if (process.env.NODE_ENV !== 'production') {
WithTheme.displayName = wrapDisplayName(Component, 'WithTheme');
}
hoistNonReactStatics(WithTheme, Component);
if (process.env.NODE_ENV !== 'production') {
// Exposed for test purposes.
WithTheme.Naked = Component;
}
return WithTheme;
};

View File

@@ -1,15 +1,14 @@
export interface ZIndex {
mobileStepper: number;
menu: number;
appBar: number;
drawerOverlay: number;
navDrawer: number;
dialogOverlay: number;
dialog: number;
layer: number;
popover: number;
drawer: number;
modal: number;
snackbar: number;
tooltip: number;
}
export default ZIndex;
export type ZIndexOptions = Partial<ZIndex>;
declare const zIndex: ZIndex;
export default zIndex;

View File

@@ -1,18 +1,12 @@
// Needed as the zIndex works with absolute values.
// We need to centralize the zIndex definitions as they work
// like global values in the browser.
const zIndex = {
mobileStepper: 900,
menu: 1000,
mobileStepper: 1000,
appBar: 1100,
drawerOverlay: 1200,
navDrawer: 1300,
dialogOverlay: 1400,
dialog: 1500,
layer: 2000,
popover: 2100,
snackbar: 2900,
tooltip: 3000
drawer: 1200,
modal: 1300,
snackbar: 1400,
tooltip: 1500
};
export default zIndex;