Added logging, changed some directory structure

This commit is contained in:
2018-01-13 21:33:40 -05:00
parent f079a5f067
commit 8e72ffb917
73656 changed files with 35284 additions and 53718 deletions

View File

@@ -0,0 +1,12 @@
import * as React from 'react';
import { Theme } from './createMuiTheme';
export interface MuiThemeProviderProps {
theme?: Theme<any>;
sheetsManager?: Object;
children: React.ReactNode;
}
declare const MuiThemeProvider: React.ComponentType<MuiThemeProviderProps>
export default MuiThemeProvider

View File

@@ -0,0 +1,127 @@
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 React from 'react';
import PropTypes from 'prop-types';
import createBroadcast from 'brcast';
import themeListener, { CHANNEL } from './themeListener';
import exactProp from '../utils/exactProp';
/**
* This component takes a `theme` property.
* It makes the `theme` available down the React tree thanks to React context.
* This component should preferably be used at **the root of your component tree**.
*/
class MuiThemeProvider extends React.Component {
constructor(props, context) {
super(props, context);
// Get the outer theme from the context, can be null
this.broadcast = createBroadcast();
this.unsubscribeId = null;
this.outerTheme = null;
this.outerTheme = themeListener.initial(context);
// Propagate the theme so it can be accessed by the children
this.broadcast.setState(this.mergeOuterLocalTheme(this.props.theme));
}
getChildContext() {
return {
[CHANNEL]: this.broadcast,
muiThemeProviderOptions: {
sheetsManager: this.props.sheetsManager,
disableStylesGeneration: this.props.disableStylesGeneration
}
};
}
componentDidMount() {
// Subscribe on the outer theme, if present
this.unsubscribeId = themeListener.subscribe(this.context, outerTheme => {
this.outerTheme = outerTheme;
// Forward the parent theme update to the children
this.broadcast.setState(this.mergeOuterLocalTheme(this.props.theme));
});
}
componentWillReceiveProps(nextProps) {
// Propagate a local theme update
if (this.props.theme !== nextProps.theme) {
this.broadcast.setState(this.mergeOuterLocalTheme(nextProps.theme));
}
}
componentWillUnmount() {
if (this.unsubscribeId !== null) {
themeListener.unsubscribe(this.context, this.unsubscribeId);
}
}
// We are not using the React state in order to avoid unnecessary rerender.
// Simple merge between the outer theme and the local theme
mergeOuterLocalTheme(localTheme) {
// To support composition of theme.
if (typeof localTheme === 'function') {
return localTheme(this.outerTheme);
}
if (!this.outerTheme) {
return localTheme;
}
return _extends({}, this.outerTheme, localTheme);
}
render() {
return this.props.children;
}
}
MuiThemeProvider.defaultProps = {
disableStylesGeneration: false,
sheetsManager: null
};
MuiThemeProvider.propTypes = {
/**
* You can only provide a single element with react@15, a node with react@16.
*/
children: PropTypes.node.isRequired,
/**
* You can disable the generation of the styles with this option.
* It can be useful when traversing the React tree outside of the HTML
* rendering step on the server.
* Let's say you are using react-apollo to extract all
* the queries made by the interface server side.
* You can significantly speed up the traversal with this property.
*/
disableStylesGeneration: PropTypes.bool,
/**
* The sheetsManager is used to deduplicate style sheet injection in the page.
* It's deduplicating using the (theme, styles) couple.
* On the server, you should provide a new instance for each request.
*/
sheetsManager: PropTypes.object,
/**
* A theme object.
*/
theme: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired
};
MuiThemeProvider.childContextTypes = _extends({}, themeListener.contextTypes, {
muiThemeProviderOptions: PropTypes.object
});
MuiThemeProvider.contextTypes = themeListener.contextTypes;
// 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;

View File

@@ -0,0 +1,18 @@
export type ColorFormat = 'rgb' | 'rgba' | 'hsl' | 'hsla';
export type ColorObject = {
type: ColorFormat;
color: [number, number, number] | [number, number, number, number];
};
export function convertColorToString(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 getLuminance(color: string): number;
export function emphasize(color: string, coefficient?: number): string;
export function fade(color: string, value: number): string;
export function darken(color: string, coefficient?: number): string;
export function lighten(color: string, coefficient?: number): string;

View File

@@ -0,0 +1,218 @@
// weak
/* eslint-disable no-use-before-define */
/**
* Returns a number whose value is limited to the given range.
*
* @param {number} value The value to be clamped
* @param {number} min The lower boundary of the output range
* @param {number} max The upper boundary of the output range
* @returns {number} A number in the range [min, max]
*/
function clamp(value, min, max) {
if (value < min) {
return min;
}
if (value > max) {
return 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.
*
* @param {string} color - Hex color, i.e. #nnn or #nnnnnn
* @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;
}
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})`;
}
/**
* Returns an object with the type and values of a 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
*/
export function decomposeColor(color) {
if (color.charAt(0) === '#') {
return decomposeColor(convertHexToRGB(color));
}
const marker = color.indexOf('(');
const type = color.substring(0, marker);
let values = color.substring(marker + 1, color.length - 1).split(',');
values = values.map(value => parseFloat(value));
return { type, values };
}
/**
* Calculates the contrast ratio between two colors.
*
* Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
*
* @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.
*/
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
}
/**
* 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
*
* @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
*/
export function getLuminance(color) {
const decomposedColor = decomposeColor(color);
if (decomposedColor.type.indexOf('rgb') > -1) {
const rgb = decomposedColor.values.map(val => {
val /= 255; // normalized
return val <= 0.03928 ? val / 12.92 : Math.pow((val + 0.055) / 1.055, 2.4);
});
// Truncate at 3 digits
return Number((0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2]).toFixed(3));
} else if (decomposedColor.type.indexOf('hsl') > -1) {
return decomposedColor.values[2] / 100;
}
throw new Error(`Material-UI: unsupported \`${color}\` color.`);
}
/**
* Darken or lighten a colour, depending on its luminance.
* Light colors are darkened, dark colors are lightened.
*
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
* @param {number} coefficient=0.15 - multiplier in the range 0 - 1
* @returns {string} A CSS color string. Hex input values are returned as rgb
*/
export function emphasize(color, coefficient = 0.15) {
return getLuminance(color) > 0.5 ? darken(color, coefficient) : lighten(color, coefficient);
}
/**
* Set the absolute transparency of a color.
* Any existing alpha values are overwritten.
*
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
* @param {number} value - value to set the alpha channel to in the range 0 -1
* @returns {string} A CSS color string. Hex input values are returned as rgb
*/
export function fade(color, value) {
color = decomposeColor(color);
value = clamp(value, 0, 1);
if (color.type === 'rgb' || color.type === 'hsl') {
color.type += 'a';
}
color.values[3] = value;
return convertColorToString(color);
}
/**
* Darkens a color.
*
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
* @param {number} coefficient - multiplier in the range 0 - 1
* @returns {string} A CSS color string. Hex input values are returned as rgb
*/
export function darken(color, coefficient) {
color = decomposeColor(color);
coefficient = clamp(coefficient, 0, 1);
if (color.type.indexOf('hsl') > -1) {
color.values[2] *= 1 - coefficient;
} else if (color.type.indexOf('rgb') > -1) {
for (let i = 0; i < 3; i += 1) {
color.values[i] *= 1 - coefficient;
}
}
return convertColorToString(color);
}
/**
* Lightens a color.
*
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
* @param {number} coefficient - multiplier in the range 0 - 1
* @returns {string} A CSS color string. Hex input values are returned as rgb
*/
export function lighten(color, coefficient) {
color = decomposeColor(color);
coefficient = clamp(coefficient, 0, 1);
if (color.type.indexOf('hsl') > -1) {
color.values[2] += (100 - color.values[2]) * coefficient;
} else if (color.type.indexOf('rgb') > -1) {
for (let i = 0; i < 3; i += 1) {
color.values[i] += (255 - color.values[i]) * coefficient;
}
}
return convertColorToString(color);
}

View File

@@ -0,0 +1,23 @@
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;
values: BreakpointValues;
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;

View File

@@ -0,0 +1,69 @@
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; }
// 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 {
values = {
xs: 360,
sm: 600,
md: 960,
lg: 1280,
xl: 1920
},
unit = 'px',
step = 5
} = 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;
}
return `@media (min-width:${value}${unit})`;
}
function down(key) {
const value = values[key] || 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})`;
}
function only(key) {
const keyIndex = keys.indexOf(key);
if (keyIndex === keys.length - 1) {
return up(key);
}
return between(key, key);
}
function width(key) {
return values[key];
}
return _extends({
keys,
values,
up,
down,
between,
only,
width
}, other);
}

View File

@@ -0,0 +1,8 @@
/**
* 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;

View File

@@ -0,0 +1,43 @@
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
// https://github.com/cssinjs/jss/blob/4e6a05dd3f7b6572fdd3ab216861d9e446c20331/src/utils/createGenerateClassName.js
export default function createGenerateClassName() {
let ruleCounter = 0;
if (process.env.NODE_ENV === 'production' && typeof window !== 'undefined') {
generatorCounter += 1;
if (generatorCounter > 2) {
// eslint-disable-next-line no-console
console.error(['Material-UI: we have detected more than needed creation of the class name generator.', 'You should only use one class name generator on the client side.', 'If you do otherwise, you take the risk to have conflicting class names in production.'].join('\n'));
}
}
return (rule, sheet) => {
ruleCounter += 1;
warning(ruleCounter < 1e10, ['Material-UI: you might have a memory leak.', 'The ruleCounter is not supposed to grow that much.'].join(''));
if (process.env.NODE_ENV === 'production') {
return `c${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), '-');
return `${meta}-${rule.key}-${ruleCounter}`;
}
return `${rule.key}-${ruleCounter}`;
};
}

View File

@@ -0,0 +1,13 @@
import { Breakpoints } from './createBreakpoints';
import { Spacing } from './spacing';
export interface Mixins {
gutters: (styles: Object) => Object;
toolbar: Object;
}
export default function createMixins<T = {}>(
breakpoints: Breakpoints,
spacing: Spacing,
mixins: T
): Mixins & T;

View File

@@ -0,0 +1,24 @@
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; };
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;
},
toolbar: {
minHeight: 56,
[`${breakpoints.up('xs')} and (orientation: landscape)`]: {
minHeight: 48
},
[breakpoints.up('sm')]: {
minHeight: 64
}
}
}, mixins);
}

View File

@@ -0,0 +1,31 @@
import { Breakpoints, BreakpointsOptions } from './createBreakpoints';
import { Mixins } from './createMixins';
import { Palette } from './createPalette';
import { Shadows } from './shadows';
import { Spacing } from './spacing';
import { Transitions } from './transitions';
import { Typography, TypographyOptions } from './createTypography';
import { ZIndex } from './zIndex';
export interface ThemeOptions {
breakpoints?: Partial<BreakpointsOptions> & Partial<Breakpoints>;
mixins?: Partial<Mixins>;
palette?: Partial<Palette>;
typography?: TypographyOptions | ((palette: Palette) => TypographyOptions);
}
export type Theme<T = {}> = {
direction: 'ltr' | 'rtl';
palette: Palette;
typography: Typography;
mixins: Mixins;
breakpoints: Breakpoints;
shadows: Shadows;
transitions: Transitions;
spacing: Spacing;
zIndex: ZIndex;
} & T;
export default function createMuiTheme<T = {}>(
options?: ThemeOptions & T
): Theme<T>;

View File

@@ -0,0 +1,47 @@
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 deepmerge from 'deepmerge'; // < 1kb payload overhead when lodash/merge is > 3kb.
import warning from 'warning';
import createTypography from './createTypography';
import createBreakpoints from './createBreakpoints';
import createPalette from './createPalette';
import createMixins from './createMixins';
import shadows from './shadows';
import transitions from './transitions';
import zIndex from './zIndex';
import spacing from './spacing';
function createMuiTheme(options = {}) {
const {
palette: paletteInput = {},
breakpoints: breakpointsInput = {},
mixins: mixinsInput = {},
typography: typographyInput = {},
shadows: shadowsInput
} = options,
other = _objectWithoutProperties(options, ['palette', 'breakpoints', 'mixins', 'typography', 'shadows']);
const palette = createPalette(paletteInput);
const breakpoints = createBreakpoints(breakpointsInput);
const muiTheme = _extends({
direction: 'ltr',
palette,
typography: createTypography(palette, typographyInput),
mixins: createMixins(breakpoints, spacing, mixinsInput),
breakpoints,
shadows: shadowsInput || shadows
}, deepmerge({
transitions,
spacing,
zIndex
}, other));
warning(muiTheme.shadows.length === 25, 'Material-UI: the shadows array provided to createMuiTheme should support 25 elevations.');
return muiTheme;
}
export default createMuiTheme;

View File

@@ -0,0 +1,65 @@
import { Color, Contrast } from '..';
import commonColors from '../colors/common';
type ShadeText = {
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 = {
active: string;
disabled: string;
};
type ShadeBackground = {
default: string;
paper: string;
appBar: string;
contentFrame: string;
status: string;
};
export type Shade = {
text: ShadeText;
input: ShadeInput;
action: ShadeAction;
background: ShadeBackground;
};
export const light: Shade;
export const dark: Shade;
export type Palette = {
common: typeof commonColors;
type: Contrast;
primary: Color;
secondary: Color;
error: Color;
grey: Color;
shades: {
dark: Shade;
light: Shade;
};
text: ShadeText;
input: ShadeInput;
action: ShadeAction;
background: ShadeBackground;
getContrastText: (color: string) => string;
};
export default function createPalette(
palette: Partial<Palette>
): Palette;

View File

@@ -0,0 +1,123 @@
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 warning from 'warning';
import deepmerge from 'deepmerge'; // < 1kb payload overhead when lodash/merge is > 3kb.
import indigo from '../colors/indigo';
import pink from '../colors/pink';
import grey from '../colors/grey';
import red from '../colors/red';
import common from '../colors/common';
import { getContrastRatio } from './colorManipulator';
export const light = {
text: {
primary: 'rgba(0, 0, 0, 0.87)',
secondary: 'rgba(0, 0, 0, 0.54)',
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)'
},
background: {
default: grey[50],
paper: common.white,
appBar: grey[100],
contentFrame: grey[200]
}
};
export const dark = {
text: {
primary: 'rgba(255, 255, 255, 1)',
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)'
},
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)'
},
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]
}
};
function getContrastText(color) {
if (getContrastRatio(color, common.black) < 7) {
return dark.text.primary;
}
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 };
warning(Boolean(shades[type]), `Material-UI: the palette type \`${type}\` is not supported.`);
const paletteOutput = deepmerge({
common,
type,
primary,
secondary,
error,
grey,
shades,
text: shades[type].text,
input: shades[type].input,
action: shades[type].action,
background: shades[type].background,
getContrastText
}, 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

@@ -0,0 +1,44 @@
import * as React from 'react';
import { Palette } from './createPalette';
export type TextStyle =
| 'display1'
| 'display2'
| 'display3'
| 'display4'
| 'headline'
| 'title'
| 'subheading'
| 'body1'
| 'body2'
| 'caption';
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;
htmlFontSize?: number;
}
export interface TypographyStyle {
color?: React.CSSProperties['color'];
fontFamily: React.CSSProperties['fontFamily'];
fontSize: React.CSSProperties['fontSize'];
fontWeight: React.CSSProperties['fontWeight'];
letterSpacing?: React.CSSProperties['letterSpacing'];
lineHeight: React.CSSProperties['lineHeight'];
textTransform?: React.CSSProperties['textTransform'];
}
export type Typography = { [type in Style]: TypographyStyle } & FontStyle;
export type TypographyOptions = Partial<FontStyle> & Partial<Typography>;
export default function createTypography(
palette: Palette,
typography: TypographyOptions | ((palette: Palette) => TypographyOptions)
): Typography;

View File

@@ -0,0 +1,116 @@
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 deepmerge from 'deepmerge'; // < 1kb payload overhead when lodash/merge is > 3kb.
function round(value) {
return Math.round(value * 1e5) / 1e5;
}
export default function createTypography(palette, typography) {
const _ref = typeof typography === 'function' ? typography(palette) : typography,
{
fontFamily = '"Roboto", "Helvetica", "Arial", sans-serif',
fontSize = 14, // px
fontWeightLight = 300,
fontWeightRegular = 400,
fontWeightMedium = 500,
htmlFontSize = 16 } = _ref,
other = _objectWithoutProperties(_ref, ['fontFamily', 'fontSize', 'fontWeightLight', 'fontWeightRegular', 'fontWeightMedium', 'htmlFontSize']);
function pxToRem(value) {
return `${value / htmlFontSize}rem`;
}
return deepmerge({
pxToRem,
fontFamily,
fontSize,
fontWeightLight,
fontWeightRegular,
fontWeightMedium,
display4: {
fontSize: pxToRem(112),
fontWeight: fontWeightLight,
fontFamily,
letterSpacing: '-.04em',
lineHeight: `${round(128 / 112)}em`,
marginLeft: '-.06em',
color: palette.text.secondary
},
display3: {
fontSize: pxToRem(56),
fontWeight: fontWeightRegular,
fontFamily,
letterSpacing: '-.02em',
lineHeight: `${round(73 / 56)}em`,
marginLeft: '-.04em',
color: palette.text.secondary
},
display2: {
fontSize: pxToRem(45),
fontWeight: fontWeightRegular,
fontFamily,
lineHeight: `${round(48 / 45)}em`,
marginLeft: '-.04em',
color: palette.text.secondary
},
display1: {
fontSize: pxToRem(34),
fontWeight: fontWeightRegular,
fontFamily,
lineHeight: `${round(41 / 34)}em`,
marginLeft: '-.04em',
color: palette.text.secondary
},
headline: {
fontSize: pxToRem(24),
fontWeight: fontWeightRegular,
fontFamily,
lineHeight: `${round(32.5 / 24)}em`,
color: palette.text.primary
},
title: {
fontSize: pxToRem(21),
fontWeight: fontWeightMedium,
fontFamily,
lineHeight: `${round(24.5 / 21)}em`,
color: palette.text.primary
},
subheading: {
fontSize: pxToRem(16),
fontWeight: fontWeightRegular,
fontFamily,
lineHeight: `${round(24 / 16)}em`,
color: palette.text.primary
},
body2: {
fontSize: pxToRem(14),
fontWeight: fontWeightMedium,
fontFamily,
lineHeight: `${round(24 / 14)}em`,
color: palette.text.primary
},
body1: {
fontSize: pxToRem(14),
fontWeight: fontWeightRegular,
fontFamily,
lineHeight: `${round(20.5 / 14)}em`,
color: palette.text.primary
},
caption: {
fontSize: pxToRem(12),
fontWeight: fontWeightRegular,
fontFamily,
lineHeight: `${round(16.5 / 12)}em`,
color: palette.text.secondary
},
button: {
fontSize: pxToRem(fontSize),
textTransform: 'uppercase',
fontWeight: fontWeightMedium,
fontFamily
}
}, other, {
clone: false // No need to clone deep
});
}

View File

@@ -0,0 +1,36 @@
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 warning from 'warning';
import deepmerge from 'deepmerge'; // < 1kb payload overhead when lodash/merge is > 3kb.
function getStylesCreator(stylesOrCreator) {
function create(theme, name) {
const styles = typeof stylesOrCreator === 'function' ? stylesOrCreator(theme) : stylesOrCreator;
if (!theme.overrides || !name || !theme.overrides[name]) {
return styles;
}
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'));
stylesWithOverrides[key] = deepmerge(stylesWithOverrides[key], overrides[key]);
});
return stylesWithOverrides;
}
return {
create,
options: {
index: undefined
},
themingEnabled: typeof stylesOrCreator === 'function'
};
}
export default getStylesCreator;

View File

@@ -0,0 +1,4 @@
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';

View File

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

View File

@@ -0,0 +1,28 @@
export type Shadows = [
'none',
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string,
string
];
export default Shadows;

View File

@@ -0,0 +1,11 @@
const shadowKeyUmbraOpacity = 0.2;
const shadowKeyPenumbraOpacity = 0.14;
const shadowAmbientShadowOpacity = 0.12;
function createShadow(...px) {
return [`${px[0]}px ${px[1]}px ${px[2]}px ${px[3]}px rgba(0, 0, 0, ${shadowKeyUmbraOpacity})`, `${px[4]}px ${px[5]}px ${px[6]}px ${px[7]}px rgba(0, 0, 0, ${shadowKeyPenumbraOpacity})`, `${px[8]}px ${px[9]}px ${px[10]}px ${px[11]}px rgba(0, 0, 0, ${shadowAmbientShadowOpacity})`].join(',');
}
const shadows = ['none', createShadow(0, 1, 3, 0, 0, 1, 1, 0, 0, 2, 1, -1), createShadow(0, 1, 5, 0, 0, 2, 2, 0, 0, 3, 1, -2), createShadow(0, 1, 8, 0, 0, 3, 4, 0, 0, 3, 3, -2), createShadow(0, 2, 4, -1, 0, 4, 5, 0, 0, 1, 10, 0), createShadow(0, 3, 5, -1, 0, 5, 8, 0, 0, 1, 14, 0), createShadow(0, 3, 5, -1, 0, 6, 10, 0, 0, 1, 18, 0), createShadow(0, 4, 5, -2, 0, 7, 10, 1, 0, 2, 16, 1), createShadow(0, 5, 5, -3, 0, 8, 10, 1, 0, 3, 14, 2), createShadow(0, 5, 6, -3, 0, 9, 12, 1, 0, 3, 16, 2), createShadow(0, 6, 6, -3, 0, 10, 14, 1, 0, 4, 18, 3), createShadow(0, 6, 7, -4, 0, 11, 15, 1, 0, 4, 20, 3), createShadow(0, 7, 8, -4, 0, 12, 17, 2, 0, 5, 22, 4), createShadow(0, 7, 8, -4, 0, 13, 19, 2, 0, 5, 24, 4), createShadow(0, 7, 9, -4, 0, 14, 21, 2, 0, 5, 26, 4), createShadow(0, 8, 9, -5, 0, 15, 22, 2, 0, 6, 28, 5), createShadow(0, 8, 10, -5, 0, 16, 24, 2, 0, 6, 30, 5), createShadow(0, 8, 11, -5, 0, 17, 26, 2, 0, 6, 32, 5), createShadow(0, 9, 11, -5, 0, 18, 28, 2, 0, 7, 34, 6), createShadow(0, 9, 12, -6, 0, 19, 29, 2, 0, 7, 36, 6), createShadow(0, 10, 13, -6, 0, 20, 31, 3, 0, 8, 38, 7), createShadow(0, 10, 13, -6, 0, 21, 33, 3, 0, 8, 40, 7), createShadow(0, 10, 14, -6, 0, 22, 35, 3, 0, 8, 42, 7), createShadow(0, 11, 14, -7, 0, 23, 36, 3, 0, 9, 44, 8), createShadow(0, 11, 15, -7, 0, 24, 38, 3, 0, 9, 46, 8)];
export default shadows;

View File

@@ -0,0 +1,4 @@
export type Spacing = {
unit: number;
};
export default Spacing;

View File

@@ -0,0 +1,5 @@
export default {
// All components align to an 8dp square baseline grid for mobile, tablet, and desktop.
// https://material.io/guidelines/layout/metrics-keylines.html#metrics-keylines-baseline-grids
unit: 8
};

View File

@@ -0,0 +1,15 @@
// This is using the API from https://github.com/vesparny/brcast
interface MuiContext {
getState(): Object;
subscribe(callback: Function): Function;
}
export interface ThemeListener {
contextTypes: {
'material-ui': object;
};
initial(context: Object): Object;
subscribe(context: Object, callback: Function): Function;
}
export default ThemeListener;

View File

@@ -0,0 +1,31 @@
import PropTypes from 'prop-types';
// Same value used by react-jss
export const CHANNEL = '__THEMING__';
const themeListener = {
contextTypes: {
[CHANNEL]: PropTypes.object
},
initial: context => {
if (!context[CHANNEL]) {
return null;
}
return context[CHANNEL].getState();
},
subscribe: (context, cb) => {
if (!context[CHANNEL]) {
return null;
}
return context[CHANNEL].subscribe(cb);
},
unsubscribe(context, subscriptionId) {
if (context[CHANNEL]) {
context[CHANNEL].unsubscribe(subscriptionId);
}
}
};
export default themeListener;

View File

@@ -0,0 +1,32 @@
export interface Easing {
easeInOut: string;
easeOut: string;
easeIn: string;
sharp: string;
}
export const easing: Easing;
export interface Duration {
shortest: number;
shorter: number;
short: number;
standard: number;
complex: number;
enteringScreen: number;
leavingScreen: number;
}
export const duration: Duration;
export function formatMs(milliseconds: number): string;
export interface Transitions {
easing: Easing;
duration: Duration;
create(
props: string | string[],
options?: Partial<{ duration: number; easing: string; delay: number }>
): string;
getAutoHeightDuration(height: number): number;
}
export default Transitions;

View File

@@ -0,0 +1,78 @@
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; }
/* eslint-disable no-param-reassign */
import warning from 'warning';
// Follow https://material.google.com/motion/duration-easing.html#duration-easing-natural-easing-curves
// to learn the context in which each easing should be used.
export const easing = {
// This is the most common easing curve.
easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
// Objects enter the screen at full velocity from off-screen and
// slowly decelerate to a resting point.
easeOut: 'cubic-bezier(0.0, 0, 0.2, 1)',
// Objects leave the screen at full velocity. They do not decelerate when off-screen.
easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
// The sharp curve is used by objects that may return to the screen at any time.
sharp: 'cubic-bezier(0.4, 0, 0.6, 1)'
};
// Follow https://material.io/guidelines/motion/duration-easing.html#duration-easing-common-durations
// to learn when use what timing
export const duration = {
shortest: 150,
shorter: 200,
short: 250,
// most basic recommended timing
standard: 300,
// this is to be used in complex animations
complex: 375,
// recommended when something is entering screen
enteringScreen: 225,
// recommended when something is leaving screen
leavingScreen: 195
};
export const formatMs = milliseconds => `${Math.round(milliseconds)}ms`;
export const isString = value => typeof value === 'string';
export const isNumber = value => !Number.isNaN(parseFloat(value));
/**
* @param {string|Array} props
* @param {object} param
* @param {string} param.prop
* @param {number} param.duration
* @param {string} param.easing
* @param {number} param.delay
*/
export default {
easing,
duration,
create(props = ['all'], options = {}) {
const {
duration: durationOption = duration.standard,
easing: easingOption = easing.easeInOut,
delay = 0
} = 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(',')}]`);
return (Array.isArray(props) ? props : [props]).map(animatedProp => `${animatedProp} ${formatMs(durationOption)} ${easingOption} ${formatMs(delay)}`).join(',');
},
getAutoHeightDuration(height) {
if (!height) {
return 0;
}
const constant = height / 36;
// https://www.wolframalpha.com/input/?i=(4+%2B+15+*+(x+%2F+36+)+**+0.25+%2B+(x+%2F+36)+%2F+5)+*+10
return Math.round((4 + 15 * Math.pow(constant, 0.25) + constant / 5) * 10);
}
};

View File

@@ -0,0 +1,38 @@
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>>;
export type StyleRulesCallback<ClassKey extends string = string> = (theme: Theme) => StyleRules<ClassKey>;
export interface WithStylesOptions {
flip?: boolean;
withTheme?: boolean;
name?: string;
}
export type ClassNameMap<ClassKey extends string = string> = Record<ClassKey, string>;
export interface WithStyles<ClassKey extends string = string> {
classes: ClassNameMap<ClassKey>
theme?: Theme
}
export interface StyledComponentProps<ClassKey extends string = string> {
classes?: Partial<ClassNameMap<ClassKey>>;
innerRef?: React.Ref<any>;
}
export default function withStyles<ClassKey extends string>(
style: StyleRules<ClassKey> | StyleRulesCallback<ClassKey>,
options?: WithStylesOptions
): <P>(
component: React.ComponentType<P & WithStyles<ClassKey>>
) => React.ComponentType<P & StyledComponentProps<ClassKey>>;

View File

@@ -0,0 +1,289 @@
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 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 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 createMuiTheme from './createMuiTheme';
import themeListener from './themeListener';
import createGenerateClassName from './createGenerateClassName';
import getStylesCreator from './getStylesCreator';
// New JSS instance.
const jss = create(preset());
// Use a singleton or the provided one by the context.
const generateClassName = createGenerateClassName();
// Global index counter to preserve source order.
// As we create the style sheet during componentWillMount lifecycle,
// children are handled after the parents, so the order of style elements would
// be parent->child. It is a problem though when a parent passes a className
// which needs to override any childs styles. StyleSheet of the child has a higher
// 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;
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 = {};
// In order to have self-supporting components, we rely on default theme when not provided.
let defaultTheme;
function getDefaultTheme() {
if (defaultTheme) {
return defaultTheme;
}
defaultTheme = createMuiTheme();
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,
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;
}
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 {
constructor(props, context) {
super(props, context);
this.state = {};
this.unsubscribeId = null;
this.jss = null;
this.sheetsManager = sheetsManager;
this.disableStylesGeneration = false;
this.stylesCreatorSaved = null;
this.theme = null;
this.sheetOptions = null;
this.theme = null;
const { muiThemeProviderOptions } = this.context;
this.jss = this.context[ns.jss] || jss;
if (muiThemeProviderOptions) {
if (muiThemeProviderOptions.sheetsManager) {
this.sheetsManager = muiThemeProviderOptions.sheetsManager;
}
this.disableStylesGeneration = muiThemeProviderOptions.disableStylesGeneration;
}
// Attach the stylesCreator to the instance of the component as in the context
// of react-hot-loader the hooks can be executed in a different closure context:
// https://github.com/gaearon/react-hot-loader/blob/master/src/patch.dev.js#L107
this.stylesCreatorSaved = stylesCreator;
this.sheetOptions = _extends({
generateClassName
}, this.context[ns.sheetOptions]);
// We use || as it's lazy evaluated.
this.theme = listenToTheme ? themeListener.initial(context) || getDefaultTheme() : noopTheme;
}
// Exposed for test purposes.
// Exposed for tests purposes
componentWillMount() {
this.attach(this.theme);
}
componentDidMount() {
if (!listenToTheme) {
return;
}
this.unsubscribeId = themeListener.subscribe(this.context, theme => {
const oldTheme = this.theme;
this.theme = theme;
this.attach(this.theme);
// Rerender the component so the underlying component gets the theme update.
// By theme update we mean receiving and applying the new class names.
this.setState({}, () => {
this.detach(oldTheme);
});
});
}
componentWillReceiveProps() {
// react-hot-loader specific logic
if (this.stylesCreatorSaved === stylesCreator || process.env.NODE_ENV === 'production') {
return;
}
this.detach(this.theme);
this.stylesCreatorSaved = stylesCreator;
this.attach(this.theme);
}
componentWillUnmount() {
this.detach(this.theme);
if (this.unsubscribeId !== null) {
themeListener.unsubscribe(this.context, this.unsubscribeId);
}
}
attach(theme) {
if (this.disableStylesGeneration) {
return;
}
const stylesCreatorSaved = this.stylesCreatorSaved;
let sheetManager = this.sheetsManager.get(stylesCreatorSaved);
if (!sheetManager) {
sheetManager = new Map();
this.sheetsManager.set(stylesCreatorSaved, sheetManager);
}
let sheetManagerTheme = sheetManager.get(theme);
if (!sheetManagerTheme) {
sheetManagerTheme = {
refs: 0,
sheet: null
};
sheetManager.set(theme, sheetManagerTheme);
}
if (sheetManagerTheme.refs === 0) {
const styles = stylesCreatorSaved.create(theme, name);
let meta;
if (process.env.NODE_ENV !== 'production') {
meta = name || getDisplayName(Component);
}
const sheet = this.jss.createStyleSheet(styles, _extends({
meta,
flip: typeof flip === 'boolean' ? flip : theme.direction === 'rtl',
link: false
}, this.sheetOptions, stylesCreatorSaved.options, {
name
}, styleSheetOptions));
sheetManagerTheme.sheet = sheet;
sheet.attach();
const sheetsRegistry = this.context[ns.sheetsRegistry];
if (sheetsRegistry) {
sheetsRegistry.add(sheet);
}
}
sheetManagerTheme.refs += 1;
}
detach(theme) {
if (this.disableStylesGeneration) {
return;
}
const stylesCreatorSaved = this.stylesCreatorSaved;
const sheetManager = this.sheetsManager.get(stylesCreatorSaved);
const sheetManagerTheme = sheetManager.get(theme);
sheetManagerTheme.refs -= 1;
if (sheetManagerTheme.refs === 0) {
sheetManager.delete(theme);
this.jss.removeStyleSheet(sheetManagerTheme.sheet);
const sheetsRegistry = this.context[ns.sheetsRegistry];
if (sheetsRegistry) {
sheetsRegistry.remove(sheetManagerTheme.sheet);
}
}
}
render() {
const _props = this.props,
{ classes: classesProp, innerRef } = _props,
other = _objectWithoutProperties(_props, ['classes', 'innerRef']);
let classes;
let renderedClasses = {};
if (!this.disableStylesGeneration) {
const sheetManager = this.sheetsManager.get(this.stylesCreatorSaved);
const sheetsManagerTheme = sheetManager.get(this.theme);
renderedClasses = sheetsManagerTheme.sheet.classes;
}
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'));
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'));
if (classesProp[key]) {
accumulator[key] = `${renderedClasses[key]} ${classesProp[key]}`;
}
return accumulator;
}, {}));
} else {
classes = renderedClasses;
}
const more = {};
// Provide the theme to the wrapped component.
// So we don't have to use the `withTheme()` Higher-order Component.
if (withTheme) {
more.theme = this.theme;
}
return React.createElement(Component, _extends({ classes: classes }, more, other, { ref: innerRef }));
}
}
Style.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');
}
return Style;
};
export default withStyles;

View File

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

View File

@@ -0,0 +1,63 @@
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 React from 'react';
import wrapDisplayName from 'recompose/wrapDisplayName';
import createMuiTheme from './createMuiTheme';
import themeListener from './themeListener';
let defaultTheme;
function getDefaultTheme() {
if (defaultTheme) {
return defaultTheme;
}
defaultTheme = createMuiTheme();
return defaultTheme;
}
// 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.
theme: themeListener.initial(context) || getDefaultTheme()
};
}
// Exposed for test purposes.
componentDidMount() {
this.unsubscribeId = themeListener.subscribe(this.context, theme => {
this.setState({ theme });
});
}
componentWillUnmount() {
if (this.unsubscribeId !== null) {
themeListener.unsubscribe(this.context, this.unsubscribeId);
}
}
render() {
return React.createElement(Component, _extends({ theme: this.state.theme }, this.props));
}
}
WithTheme.contextTypes = themeListener.contextTypes;
WithTheme.displayName = wrapDisplayName(Component, 'withTheme');
WithTheme.Naked = Component;
return WithTheme;
};
export default withTheme;

View File

@@ -0,0 +1,15 @@
export interface ZIndex {
mobileStepper: number;
menu: number;
appBar: number;
drawerOverlay: number;
navDrawer: number;
dialogOverlay: number;
dialog: number;
layer: number;
popover: number;
snackbar: number;
tooltip: number;
}
export default ZIndex;

View File

@@ -0,0 +1,18 @@
// Needed as the zIndex works with absolute values.
const zIndex = {
mobileStepper: 900,
menu: 1000,
appBar: 1100,
drawerOverlay: 1200,
navDrawer: 1300,
dialogOverlay: 1400,
dialog: 1500,
layer: 2000,
popover: 2100,
snackbar: 2900,
tooltip: 3000
};
export default zIndex;