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,195 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _brcast = require('brcast');
var _brcast2 = _interopRequireDefault(_brcast);
var _themeListener = require('./themeListener');
var _themeListener2 = _interopRequireDefault(_themeListener);
var _exactProp = require('../utils/exactProp');
var _exactProp2 = _interopRequireDefault(_exactProp);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* 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**.
*/
var MuiThemeProvider = function (_React$Component) {
(0, _inherits3.default)(MuiThemeProvider, _React$Component);
function MuiThemeProvider(props, context) {
(0, _classCallCheck3.default)(this, MuiThemeProvider);
// Get the outer theme from the context, can be null
var _this = (0, _possibleConstructorReturn3.default)(this, (MuiThemeProvider.__proto__ || (0, _getPrototypeOf2.default)(MuiThemeProvider)).call(this, props, context));
_this.broadcast = (0, _brcast2.default)();
_this.unsubscribeId = null;
_this.outerTheme = null;
_this.outerTheme = _themeListener2.default.initial(context);
// Propagate the theme so it can be accessed by the children
_this.broadcast.setState(_this.mergeOuterLocalTheme(_this.props.theme));
return _this;
}
(0, _createClass3.default)(MuiThemeProvider, [{
key: 'getChildContext',
value: function getChildContext() {
var _ref;
return _ref = {}, (0, _defineProperty3.default)(_ref, _themeListener.CHANNEL, this.broadcast), (0, _defineProperty3.default)(_ref, 'muiThemeProviderOptions', {
sheetsManager: this.props.sheetsManager,
disableStylesGeneration: this.props.disableStylesGeneration
}), _ref;
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var _this2 = this;
// Subscribe on the outer theme, if present
this.unsubscribeId = _themeListener2.default.subscribe(this.context, function (outerTheme) {
_this2.outerTheme = outerTheme;
// Forward the parent theme update to the children
_this2.broadcast.setState(_this2.mergeOuterLocalTheme(_this2.props.theme));
});
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
// Propagate a local theme update
if (this.props.theme !== nextProps.theme) {
this.broadcast.setState(this.mergeOuterLocalTheme(nextProps.theme));
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
if (this.unsubscribeId !== null) {
_themeListener2.default.unsubscribe(this.context, this.unsubscribeId);
}
}
// We are not using the React state in order to avoid unnecessary rerender.
}, {
key: 'mergeOuterLocalTheme',
// Simple merge between the outer theme and the local theme
value: function mergeOuterLocalTheme(localTheme) {
// To support composition of theme.
if (typeof localTheme === 'function') {
return localTheme(this.outerTheme);
}
if (!this.outerTheme) {
return localTheme;
}
return (0, _extends3.default)({}, this.outerTheme, localTheme);
}
}, {
key: 'render',
value: function render() {
return this.props.children;
}
}]);
return MuiThemeProvider;
}(_react2.default.Component);
MuiThemeProvider.defaultProps = {
disableStylesGeneration: false,
sheetsManager: null
};
MuiThemeProvider.propTypes = process.env.NODE_ENV !== "production" ? {
/**
* You can only provide a single element with react@15, a node with react@16.
*/
children: _propTypes2.default.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: _propTypes2.default.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: _propTypes2.default.object,
/**
* A theme object.
*/
theme: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.func]).isRequired
} : {};
MuiThemeProvider.childContextTypes = (0, _extends3.default)({}, _themeListener2.default.contextTypes, {
muiThemeProviderOptions: _propTypes2.default.object
});
MuiThemeProvider.contextTypes = _themeListener2.default.contextTypes;
// Add a wrapper component to generate some helper messages in the development
// environment.
// eslint-disable-next-line import/no-mutable-exports
var MuiThemeProviderWrapper = MuiThemeProvider;
if (process.env.NODE_ENV !== 'production') {
MuiThemeProviderWrapper = function MuiThemeProviderWrapper(props) {
return _react2.default.createElement(MuiThemeProvider, props);
};
MuiThemeProviderWrapper.propTypes = (0, _exactProp2.default)(MuiThemeProvider.propTypes, 'MuiThemeProvider');
}
exports.default = MuiThemeProviderWrapper;

View File

@@ -0,0 +1,128 @@
// @flow
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<Object> {
static defaultProps = {
disableStylesGeneration: false,
sheetsManager: null,
};
constructor(props: Object, context: Object) {
super(props, context);
// Get the outer theme from the context, can be 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: Object) {
// 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);
}
}
broadcast = createBroadcast();
unsubscribeId = null;
// We are not using the React state in order to avoid unnecessary rerender.
outerTheme = null;
// Simple merge between the outer theme and the local theme
mergeOuterLocalTheme(localTheme: Object) {
// To support composition of theme.
if (typeof localTheme === 'function') {
return localTheme(this.outerTheme);
}
if (!this.outerTheme) {
return localTheme;
}
return { ...this.outerTheme, ...localTheme };
}
render() {
return this.props.children;
}
}
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 = {
...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: any) => <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,238 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.convertColorToString = convertColorToString;
exports.convertHexToRGB = convertHexToRGB;
exports.decomposeColor = decomposeColor;
exports.getContrastRatio = getContrastRatio;
exports.getLuminance = getLuminance;
exports.emphasize = emphasize;
exports.fade = fade;
exports.darken = darken;
exports.lighten = lighten;
// 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
*/
function convertColorToString(color) {
var type = color.type,
values = color.values;
if (type.indexOf('rgb') > -1) {
// Only convert the first 3 values to int (i.e. not alpha)
for (var i = 0; i < 3; i += 1) {
values[i] = parseInt(values[i], 10);
}
}
var colorString = void 0;
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
*/
function convertHexToRGB(color) {
if (color.length === 4) {
var extendedColor = '#';
for (var i = 1; i < color.length; i += 1) {
extendedColor += color.charAt(i) + color.charAt(i);
}
color = extendedColor;
}
var 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
*/
function decomposeColor(color) {
if (color.charAt(0) === '#') {
return decomposeColor(convertHexToRGB(color));
}
var marker = color.indexOf('(');
var type = color.substring(0, marker);
var values = color.substring(marker + 1, color.length - 1).split(',');
values = values.map(function (value) {
return parseFloat(value);
});
return { type: type, values: 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.
*/
function getContrastRatio(foreground, background) {
var lumA = getLuminance(foreground);
var lumB = getLuminance(background);
var 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
*/
function getLuminance(color) {
var decomposedColor = decomposeColor(color);
if (decomposedColor.type.indexOf('rgb') > -1) {
var rgb = decomposedColor.values.map(function (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
*/
function emphasize(color) {
var coefficient = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 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
*/
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
*/
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 (var 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
*/
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 (var i = 0; i < 3; i += 1) {
color.values[i] += (255 - color.values[i]) * coefficient;
}
}
return convertColorToString(color);
}

View File

@@ -0,0 +1,218 @@
// @flow 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: Object) {
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: string) {
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: string) {
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: string, background: string) {
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: string) {
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: string, coefficient: number = 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: string, value: number) {
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: string, coefficient: number) {
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: string, coefficient: number) {
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,86 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.keys = undefined;
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
exports.default = createBreakpoints;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var babelPluginFlowReactPropTypes_proptype_Breakpoint = require('prop-types').oneOf(['xs', 'sm', 'md', 'lg', 'xl']);
// Sorted ASC by size. That's important.
// It can't be configured as it's used statically for propTypes.
var keys = exports.keys = ['xs', 'sm', 'md', 'lg', 'xl'];
// Keep in mind that @media is inclusive by the CSS specification.
function createBreakpoints(breakpoints) {
var _breakpoints$values = breakpoints.values,
values = _breakpoints$values === undefined ? {
xs: 360,
sm: 600,
md: 960,
lg: 1280,
xl: 1920
} : _breakpoints$values,
_breakpoints$unit = breakpoints.unit,
unit = _breakpoints$unit === undefined ? 'px' : _breakpoints$unit,
_breakpoints$step = breakpoints.step,
step = _breakpoints$step === undefined ? 5 : _breakpoints$step,
other = (0, _objectWithoutProperties3.default)(breakpoints, ['values', 'unit', 'step']);
function up(key) {
var value = void 0;
// 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) {
var value = values[key] || key;
return '@media (max-width:' + (value - step / 100) + unit + ')';
}
function between(start, end) {
var startIndex = keys.indexOf(start);
var 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) {
var keyIndex = keys.indexOf(key);
if (keyIndex === keys.length - 1) {
return up(key);
}
return between(key, key);
}
function width(key) {
return values[key];
}
return (0, _extends3.default)({
keys: keys,
values: values,
up: up,
down: down,
between: between,
only: only,
width: width
}, other);
}

View File

@@ -0,0 +1,71 @@
// @flow
export type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
// 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: Object) {
const {
values = {
xs: 360,
sm: 600,
md: 960,
lg: 1280,
xl: 1920,
},
unit = 'px',
step = 5,
...other
} = breakpoints;
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 {
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,59 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = createGenerateClassName;
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var babelPluginFlowReactPropTypes_proptype_StyleSheet = require('jss/lib/StyleSheet').babelPluginFlowReactPropTypes_proptype_StyleSheet || require('prop-types').any;
var babelPluginFlowReactPropTypes_proptype_generateClassName = require('jss/lib/types').babelPluginFlowReactPropTypes_proptype_generateClassName || require('prop-types').any;
var babelPluginFlowReactPropTypes_proptype_Rule = require('jss/lib/types').babelPluginFlowReactPropTypes_proptype_Rule || require('prop-types').any;
var 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
function createGenerateClassName() {
var 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 function (rule, sheet) {
ruleCounter += 1;
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(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;
}
if (sheet && sheet.options.meta) {
var 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,58 @@
// @flow
import warning from 'warning';
import type StyleSheet from 'jss/lib/StyleSheet';
import type { Rule, generateClassName } from 'jss/lib/types';
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(): generateClassName {
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: Rule, sheet?: StyleSheet): string => {
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,40 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
exports.default = createMixins;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function createMixins(breakpoints, spacing, mixins) {
var _toolbar;
return (0, _extends3.default)({
gutters: function 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: (_toolbar = {
minHeight: 56
}, (0, _defineProperty3.default)(_toolbar, breakpoints.up('xs') + ' and (orientation: landscape)', {
minHeight: 48
}), (0, _defineProperty3.default)(_toolbar, breakpoints.up('sm'), {
minHeight: 64
}), _toolbar)
}, mixins);
}

View File

@@ -0,0 +1,25 @@
// @flow
export default function createMixins(breakpoints: Object, spacing: Object, mixins: Object) {
return {
gutters: (styles: Object) => {
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,91 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
var _deepmerge = require('deepmerge');
var _deepmerge2 = _interopRequireDefault(_deepmerge);
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
var _createTypography = require('./createTypography');
var _createTypography2 = _interopRequireDefault(_createTypography);
var _createBreakpoints = require('./createBreakpoints');
var _createBreakpoints2 = _interopRequireDefault(_createBreakpoints);
var _createPalette = require('./createPalette');
var _createPalette2 = _interopRequireDefault(_createPalette);
var _createMixins = require('./createMixins');
var _createMixins2 = _interopRequireDefault(_createMixins);
var _shadows = require('./shadows');
var _shadows2 = _interopRequireDefault(_shadows);
var _transitions = require('./transitions');
var _transitions2 = _interopRequireDefault(_transitions);
var _zIndex = require('./zIndex');
var _zIndex2 = _interopRequireDefault(_zIndex);
var _spacing = require('./spacing');
var _spacing2 = _interopRequireDefault(_spacing);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function createMuiTheme() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _options$palette = options.palette,
paletteInput = _options$palette === undefined ? {} : _options$palette,
_options$breakpoints = options.breakpoints,
breakpointsInput = _options$breakpoints === undefined ? {} : _options$breakpoints,
_options$mixins = options.mixins,
mixinsInput = _options$mixins === undefined ? {} : _options$mixins,
_options$typography = options.typography,
typographyInput = _options$typography === undefined ? {} : _options$typography,
shadowsInput = options.shadows,
other = (0, _objectWithoutProperties3.default)(options, ['palette', 'breakpoints', 'mixins', 'typography', 'shadows']);
var palette = (0, _createPalette2.default)(paletteInput);
var breakpoints = (0, _createBreakpoints2.default)(breakpointsInput);
var muiTheme = (0, _extends3.default)({
direction: 'ltr',
palette: palette,
typography: (0, _createTypography2.default)(palette, typographyInput),
mixins: (0, _createMixins2.default)(breakpoints, _spacing2.default, mixinsInput),
breakpoints: breakpoints,
shadows: shadowsInput || _shadows2.default
}, (0, _deepmerge2.default)({
transitions: _transitions2.default,
spacing: _spacing2.default,
zIndex: _zIndex2.default
}, other));
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(muiTheme.shadows.length === 25, 'Material-UI: the shadows array provided to createMuiTheme should support 25 elevations.') : void 0;
return muiTheme;
} // < 1kb payload overhead when lodash/merge is > 3kb.
exports.default = createMuiTheme;

View File

@@ -0,0 +1,52 @@
// @flow
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: Object = {}) {
const {
palette: paletteInput = {},
breakpoints: breakpointsInput = {},
mixins: mixinsInput = {},
typography: typographyInput = {},
shadows: shadowsInput,
...other
} = options;
const palette = createPalette(paletteInput);
const breakpoints = createBreakpoints(breakpointsInput);
const muiTheme = {
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,172 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.dark = exports.light = undefined;
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
exports.default = createPalette;
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
var _deepmerge = require('deepmerge');
var _deepmerge2 = _interopRequireDefault(_deepmerge);
var _indigo = require('../colors/indigo');
var _indigo2 = _interopRequireDefault(_indigo);
var _pink = require('../colors/pink');
var _pink2 = _interopRequireDefault(_pink);
var _grey = require('../colors/grey');
var _grey2 = _interopRequireDefault(_grey);
var _red = require('../colors/red');
var _red2 = _interopRequireDefault(_red);
var _common = require('../colors/common');
var _common2 = _interopRequireDefault(_common);
var _colorManipulator = require('./colorManipulator');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// < 1kb payload overhead when lodash/merge is > 3kb.
var light = exports.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: _grey2.default[50],
paper: _common2.default.white,
appBar: _grey2.default[100],
contentFrame: _grey2.default[200]
}
};
var dark = exports.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: _grey2.default[800],
appBar: _grey2.default[900],
contentFrame: _grey2.default[900]
}
};
function getContrastText(color) {
if ((0, _colorManipulator.getContrastRatio)(color, _common2.default.black) < 7) {
return dark.text.primary;
}
return light.text.primary;
}
function createPalette(palette) {
var _palette$primary = palette.primary,
primary = _palette$primary === undefined ? _indigo2.default : _palette$primary,
_palette$secondary = palette.secondary,
secondary = _palette$secondary === undefined ? _pink2.default : _palette$secondary,
_palette$error = palette.error,
error = _palette$error === undefined ? _red2.default : _palette$error,
_palette$type = palette.type,
type = _palette$type === undefined ? 'light' : _palette$type,
other = (0, _objectWithoutProperties3.default)(palette, ['primary', 'secondary', 'error', 'type']);
var shades = { dark: dark, light: light };
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(Boolean(shades[type]), 'Material-UI: the palette type `' + type + '` is not supported.') : void 0;
var paletteOutput = (0, _deepmerge2.default)({
common: _common2.default,
type: type,
primary: primary,
secondary: secondary,
error: error,
grey: _grey2.default,
shades: shades,
text: shades[type].text,
input: shades[type].input,
action: shades[type].action,
background: shades[type].background,
getContrastText: getContrastText
}, other, {
clone: false // No need to clone deep
});
// Dev warnings
if (process.env.NODE_ENV !== 'production') {
var difference = function difference(base, compare) {
if (!compare) {
compare = {};
}
return (0, _keys2.default)(base).filter(function (hue) {
return !compare[hue];
});
};
var paletteColorError = function paletteColorError(name, base, compare) {
var missing = difference(base, compare);
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(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')) : void 0;
};
paletteColorError('primary', _indigo2.default, paletteOutput.primary);
paletteColorError('secondary', _pink2.default, paletteOutput.secondary);
paletteColorError('error', _red2.default, paletteOutput.error);
paletteColorError('grey', _red2.default, paletteOutput.grey);
}
return paletteOutput;
}

View File

@@ -0,0 +1,132 @@
// @flow
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: Object) {
const { primary = indigo, secondary = pink, error = red, type = 'light', ...other } = palette;
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,137 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
exports.default = createTypography;
var _deepmerge = require('deepmerge');
var _deepmerge2 = _interopRequireDefault(_deepmerge);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// < 1kb payload overhead when lodash/merge is > 3kb.
function round(value) {
return Math.round(value * 1e5) / 1e5;
}
function createTypography(palette, typography) {
var _ref = typeof typography === 'function' ? typography(palette) : typography,
_ref$fontFamily = _ref.fontFamily,
fontFamily = _ref$fontFamily === undefined ? '"Roboto", "Helvetica", "Arial", sans-serif' : _ref$fontFamily,
_ref$fontSize = _ref.fontSize,
fontSize = _ref$fontSize === undefined ? 14 : _ref$fontSize,
_ref$fontWeightLight = _ref.fontWeightLight,
fontWeightLight = _ref$fontWeightLight === undefined ? 300 : _ref$fontWeightLight,
_ref$fontWeightRegula = _ref.fontWeightRegular,
fontWeightRegular = _ref$fontWeightRegula === undefined ? 400 : _ref$fontWeightRegula,
_ref$fontWeightMedium = _ref.fontWeightMedium,
fontWeightMedium = _ref$fontWeightMedium === undefined ? 500 : _ref$fontWeightMedium,
_ref$htmlFontSize = _ref.htmlFontSize,
htmlFontSize = _ref$htmlFontSize === undefined ? 16 : _ref$htmlFontSize,
other = (0, _objectWithoutProperties3.default)(_ref, ['fontFamily', 'fontSize', 'fontWeightLight', 'fontWeightRegular', 'fontWeightMedium', 'htmlFontSize']);
function pxToRem(value) {
return value / htmlFontSize + 'rem';
}
return (0, _deepmerge2.default)({
pxToRem: pxToRem,
fontFamily: fontFamily,
fontSize: fontSize,
fontWeightLight: fontWeightLight,
fontWeightRegular: fontWeightRegular,
fontWeightMedium: fontWeightMedium,
display4: {
fontSize: pxToRem(112),
fontWeight: fontWeightLight,
fontFamily: fontFamily,
letterSpacing: '-.04em',
lineHeight: round(128 / 112) + 'em',
marginLeft: '-.06em',
color: palette.text.secondary
},
display3: {
fontSize: pxToRem(56),
fontWeight: fontWeightRegular,
fontFamily: fontFamily,
letterSpacing: '-.02em',
lineHeight: round(73 / 56) + 'em',
marginLeft: '-.04em',
color: palette.text.secondary
},
display2: {
fontSize: pxToRem(45),
fontWeight: fontWeightRegular,
fontFamily: fontFamily,
lineHeight: round(48 / 45) + 'em',
marginLeft: '-.04em',
color: palette.text.secondary
},
display1: {
fontSize: pxToRem(34),
fontWeight: fontWeightRegular,
fontFamily: fontFamily,
lineHeight: round(41 / 34) + 'em',
marginLeft: '-.04em',
color: palette.text.secondary
},
headline: {
fontSize: pxToRem(24),
fontWeight: fontWeightRegular,
fontFamily: fontFamily,
lineHeight: round(32.5 / 24) + 'em',
color: palette.text.primary
},
title: {
fontSize: pxToRem(21),
fontWeight: fontWeightMedium,
fontFamily: fontFamily,
lineHeight: round(24.5 / 21) + 'em',
color: palette.text.primary
},
subheading: {
fontSize: pxToRem(16),
fontWeight: fontWeightRegular,
fontFamily: fontFamily,
lineHeight: round(24 / 16) + 'em',
color: palette.text.primary
},
body2: {
fontSize: pxToRem(14),
fontWeight: fontWeightMedium,
fontFamily: fontFamily,
lineHeight: round(24 / 14) + 'em',
color: palette.text.primary
},
body1: {
fontSize: pxToRem(14),
fontWeight: fontWeightRegular,
fontFamily: fontFamily,
lineHeight: round(20.5 / 14) + 'em',
color: palette.text.primary
},
caption: {
fontSize: pxToRem(12),
fontWeight: fontWeightRegular,
fontFamily: fontFamily,
lineHeight: round(16.5 / 12) + 'em',
color: palette.text.secondary
},
button: {
fontSize: pxToRem(fontSize),
textTransform: 'uppercase',
fontWeight: fontWeightMedium,
fontFamily: fontFamily
}
}, other, {
clone: false // No need to clone deep
});
}

View File

@@ -0,0 +1,121 @@
// @flow
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: Object, typography: Object | Function) {
const {
fontFamily = '"Roboto", "Helvetica", "Arial", sans-serif',
fontSize = 14, // px
fontWeightLight = 300,
fontWeightRegular = 400,
fontWeightMedium = 500,
htmlFontSize = 16, // 16px is the default font-size used by browsers on the html element.
...other
} =
typeof typography === 'function' ? typography(palette) : typography;
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,57 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
var _deepmerge = require('deepmerge');
var _deepmerge2 = _interopRequireDefault(_deepmerge);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// < 1kb payload overhead when lodash/merge is > 3kb.
function getStylesCreator(stylesOrCreator) {
function create(theme, name) {
var styles = typeof stylesOrCreator === 'function' ? stylesOrCreator(theme) : stylesOrCreator;
if (!theme.overrides || !name || !theme.overrides[name]) {
return styles;
}
var overrides = theme.overrides[name];
var stylesWithOverrides = (0, _extends3.default)({}, styles);
(0, _keys2.default)(overrides).forEach(function (key) {
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(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')) : void 0;
stylesWithOverrides[key] = (0, _deepmerge2.default)(stylesWithOverrides[key], overrides[key]);
});
return stylesWithOverrides;
}
return {
create: create,
options: {
index: undefined
},
themingEnabled: typeof stylesOrCreator === 'function'
};
}
exports.default = getStylesCreator;

View File

@@ -0,0 +1,41 @@
// @flow
import warning from 'warning';
import deepmerge from 'deepmerge'; // < 1kb payload overhead when lodash/merge is > 3kb.
function getStylesCreator(stylesOrCreator: Object | (Object => Object)) {
function create(theme: Object, name?: string): Object {
const styles = typeof stylesOrCreator === 'function' ? stylesOrCreator(theme) : stylesOrCreator;
if (!theme.overrides || !name || !theme.overrides[name]) {
return styles;
}
const overrides = theme.overrides[name];
const stylesWithOverrides = { ...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,43 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _MuiThemeProvider = require('./MuiThemeProvider');
Object.defineProperty(exports, 'MuiThemeProvider', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_MuiThemeProvider).default;
}
});
var _withStyles = require('./withStyles');
Object.defineProperty(exports, 'withStyles', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_withStyles).default;
}
});
var _withTheme = require('./withTheme');
Object.defineProperty(exports, 'withTheme', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_withTheme).default;
}
});
var _createMuiTheme = require('./createMuiTheme');
Object.defineProperty(exports, 'createMuiTheme', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_createMuiTheme).default;
}
});
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

View File

@@ -0,0 +1,6 @@
// @flow
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,16 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var shadowKeyUmbraOpacity = 0.2;
var shadowKeyPenumbraOpacity = 0.14;
var shadowAmbientShadowOpacity = 0.12;
function createShadow() {
return [(arguments.length <= 0 ? undefined : arguments[0]) + 'px ' + (arguments.length <= 1 ? undefined : arguments[1]) + 'px ' + (arguments.length <= 2 ? undefined : arguments[2]) + 'px ' + (arguments.length <= 3 ? undefined : arguments[3]) + 'px rgba(0, 0, 0, ' + shadowKeyUmbraOpacity + ')', (arguments.length <= 4 ? undefined : arguments[4]) + 'px ' + (arguments.length <= 5 ? undefined : arguments[5]) + 'px ' + (arguments.length <= 6 ? undefined : arguments[6]) + 'px ' + (arguments.length <= 7 ? undefined : arguments[7]) + 'px rgba(0, 0, 0, ' + shadowKeyPenumbraOpacity + ')', (arguments.length <= 8 ? undefined : arguments[8]) + 'px ' + (arguments.length <= 9 ? undefined : arguments[9]) + 'px ' + (arguments.length <= 10 ? undefined : arguments[10]) + 'px ' + (arguments.length <= 11 ? undefined : arguments[11]) + 'px rgba(0, 0, 0, ' + shadowAmbientShadowOpacity + ')'].join(',');
}
var 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)];
exports.default = shadows;

View File

@@ -0,0 +1,43 @@
// @flow
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,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.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,7 @@
// @flow
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,44 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CHANNEL = undefined;
var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Same value used by react-jss
var CHANNEL = exports.CHANNEL = '__THEMING__';
var themeListener = {
contextTypes: (0, _defineProperty3.default)({}, CHANNEL, _propTypes2.default.object),
initial: function initial(context) {
if (!context[CHANNEL]) {
return null;
}
return context[CHANNEL].getState();
},
subscribe: function subscribe(context, cb) {
if (!context[CHANNEL]) {
return null;
}
return context[CHANNEL].subscribe(cb);
},
unsubscribe: function unsubscribe(context, subscriptionId) {
if (context[CHANNEL]) {
context[CHANNEL].unsubscribe(subscriptionId);
}
}
};
exports.default = themeListener;

View File

@@ -0,0 +1,33 @@
// @flow
import PropTypes from 'prop-types';
// Same value used by react-jss
export const CHANNEL = '__THEMING__';
const themeListener = {
contextTypes: {
[CHANNEL]: PropTypes.object,
},
initial: (context: Object) => {
if (!context[CHANNEL]) {
return null;
}
return context[CHANNEL].getState();
},
subscribe: (context: Object, cb: Function) => {
if (!context[CHANNEL]) {
return null;
}
return context[CHANNEL].subscribe(cb);
},
unsubscribe(context: Object, subscriptionId: number) {
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,112 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isNumber = exports.isString = exports.formatMs = exports.duration = exports.easing = undefined;
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
var _isNan = require('babel-runtime/core-js/number/is-nan');
var _isNan2 = _interopRequireDefault(_isNan);
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// 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.
var easing = exports.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
/* eslint-disable no-param-reassign */
var duration = exports.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
};
var formatMs = exports.formatMs = function formatMs(milliseconds) {
return Math.round(milliseconds) + 'ms';
};
var isString = exports.isString = function isString(value) {
return typeof value === 'string';
};
var isNumber = exports.isNumber = function isNumber(value) {
return !(0, _isNan2.default)(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
*/
exports.default = {
easing: easing,
duration: duration,
create: function create() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['all'];
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var _options$duration = options.duration,
durationOption = _options$duration === undefined ? duration.standard : _options$duration,
_options$easing = options.easing,
easingOption = _options$easing === undefined ? easing.easeInOut : _options$easing,
_options$delay = options.delay,
delay = _options$delay === undefined ? 0 : _options$delay,
other = (0, _objectWithoutProperties3.default)(options, ['duration', 'easing', 'delay']);
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(isString(props) || Array.isArray(props), 'Material-UI: argument "props" must be a string or Array') : void 0;
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(isNumber(durationOption), 'Material-UI: argument "duration" must be a number but found ' + durationOption) : void 0;
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(isString(easingOption), 'Material-UI: argument "easing" must be a string') : void 0;
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(isNumber(delay), 'Material-UI: argument "delay" must be a string') : void 0;
process.env.NODE_ENV !== "production" ? (0, _warning2.default)((0, _keys2.default)(other).length === 0, 'Material-UI: unrecognized argument(s) [' + (0, _keys2.default)(other).join(',') + ']') : void 0;
return (Array.isArray(props) ? props : [props]).map(function (animatedProp) {
return animatedProp + ' ' + formatMs(durationOption) + ' ' + easingOption + ' ' + formatMs(delay);
}).join(',');
},
getAutoHeightDuration: function getAutoHeightDuration(height) {
if (!height) {
return 0;
}
var 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,94 @@
// @flow
/* 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: number) => `${Math.round(milliseconds)}ms`;
export const isString = (value: any) => typeof value === 'string';
export const isNumber = (value: any) => !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: string | Array<string> = ['all'],
options: { prop?: string, duration?: number, easing?: string, delay?: number } = {},
) {
const {
duration: durationOption = duration.standard,
easing: easingOption = easing.easeInOut,
delay = 0,
...other
} = options;
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: ?number) {
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 * 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,423 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.sheetsManager = undefined;
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
var _map = require('babel-runtime/core-js/map');
var _map2 = _interopRequireDefault(_map);
var _minSafeInteger = require('babel-runtime/core-js/number/min-safe-integer');
var _minSafeInteger2 = _interopRequireDefault(_minSafeInteger);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
var _hoistNonReactStatics = require('hoist-non-react-statics');
var _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics);
var _wrapDisplayName = require('recompose/wrapDisplayName');
var _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName);
var _getDisplayName = require('recompose/getDisplayName');
var _getDisplayName2 = _interopRequireDefault(_getDisplayName);
var _contextTypes = require('react-jss/lib/contextTypes');
var _contextTypes2 = _interopRequireDefault(_contextTypes);
var _jss = require('jss');
var _jssPresetDefault = require('jss-preset-default');
var _jssPresetDefault2 = _interopRequireDefault(_jssPresetDefault);
var _ns = require('react-jss/lib/ns');
var ns = _interopRequireWildcard(_ns);
var _createMuiTheme = require('./createMuiTheme');
var _createMuiTheme2 = _interopRequireDefault(_createMuiTheme);
var _themeListener = require('./themeListener');
var _themeListener2 = _interopRequireDefault(_themeListener);
var _createGenerateClassName = require('./createGenerateClassName');
var _createGenerateClassName2 = _interopRequireDefault(_createGenerateClassName);
var _getStylesCreator = require('./getStylesCreator');
var _getStylesCreator2 = _interopRequireDefault(_getStylesCreator);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var babelPluginFlowReactPropTypes_proptype_HigherOrderComponent = require('react-flow-types').babelPluginFlowReactPropTypes_proptype_HigherOrderComponent || require('prop-types').any; // weak
// New JSS instance.
var jss = (0, _jss.create)((0, _jssPresetDefault2.default)());
// Use a singleton or the provided one by the context.
var generateClassName = (0, _createGenerateClassName2.default)();
// 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.
var indexCounter = _minSafeInteger2.default;
var sheetsManager = exports.sheetsManager = new _map2.default();
// We use the same empty object to ref count the styles that don't need a theme object.
var noopTheme = {};
// In order to have self-supporting components, we rely on default theme when not provided.
var defaultTheme = void 0;
function getDefaultTheme() {
if (defaultTheme) {
return defaultTheme;
}
defaultTheme = (0, _createMuiTheme2.default)();
return defaultTheme;
}
var babelPluginFlowReactPropTypes_proptype_RequiredProps = {
/**
* Useful to extend the style applied to components.
*/
classes: require('prop-types').object,
/**
* Use that property to pass a ref callback to the decorated component.
*/
innerRef: require('prop-types').func
};
var babelPluginFlowReactPropTypes_proptype_InjectedProps = {
classes: require('prop-types').object.isRequired,
theme: require('prop-types').object.isRequired
};
// 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.
var withStyles = function withStyles(stylesOrCreator) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return function (Component) {
var _options$withTheme = options.withTheme,
withTheme = _options$withTheme === undefined ? false : _options$withTheme,
flip = options.flip,
name = options.name,
styleSheetOptions = (0, _objectWithoutProperties3.default)(options, ['withTheme', 'flip', 'name']);
var stylesCreator = (0, _getStylesCreator2.default)(stylesOrCreator);
var listenToTheme = stylesCreator.themingEnabled || withTheme || typeof name === 'string';
if (stylesCreator.options.index === undefined) {
indexCounter += 1;
stylesCreator.options.index = indexCounter;
}
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(indexCounter < 0, ['Material-UI: you might have a memory leak.', 'The indexCounter is not supposed to grow that much.'].join(' ')) : void 0;
var Style = function (_React$Component) {
(0, _inherits3.default)(Style, _React$Component);
function Style(props, context) {
(0, _classCallCheck3.default)(this, Style);
var _this = (0, _possibleConstructorReturn3.default)(this, (Style.__proto__ || (0, _getPrototypeOf2.default)(Style)).call(this, 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;
var muiThemeProviderOptions = _this.context.muiThemeProviderOptions;
_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 = (0, _extends3.default)({
generateClassName: generateClassName
}, _this.context[ns.sheetOptions]);
// We use || as it's lazy evaluated.
_this.theme = listenToTheme ? _themeListener2.default.initial(context) || getDefaultTheme() : noopTheme;
return _this;
}
// Exposed for test purposes.
// Exposed for tests purposes
(0, _createClass3.default)(Style, [{
key: 'componentWillMount',
value: function componentWillMount() {
this.attach(this.theme);
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var _this2 = this;
if (!listenToTheme) {
return;
}
this.unsubscribeId = _themeListener2.default.subscribe(this.context, function (theme) {
var oldTheme = _this2.theme;
_this2.theme = theme;
_this2.attach(_this2.theme);
// Rerender the component so the underlying component gets the theme update.
// By theme update we mean receiving and applying the new class names.
_this2.setState({}, function () {
_this2.detach(oldTheme);
});
});
}
}, {
key: 'componentWillReceiveProps',
value: function 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);
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.detach(this.theme);
if (this.unsubscribeId !== null) {
_themeListener2.default.unsubscribe(this.context, this.unsubscribeId);
}
}
}, {
key: 'attach',
value: function attach(theme) {
if (this.disableStylesGeneration) {
return;
}
var stylesCreatorSaved = this.stylesCreatorSaved;
var sheetManager = this.sheetsManager.get(stylesCreatorSaved);
if (!sheetManager) {
sheetManager = new _map2.default();
this.sheetsManager.set(stylesCreatorSaved, sheetManager);
}
var sheetManagerTheme = sheetManager.get(theme);
if (!sheetManagerTheme) {
sheetManagerTheme = {
refs: 0,
sheet: null
};
sheetManager.set(theme, sheetManagerTheme);
}
if (sheetManagerTheme.refs === 0) {
var styles = stylesCreatorSaved.create(theme, name);
var _meta = void 0;
if (process.env.NODE_ENV !== 'production') {
_meta = name || (0, _getDisplayName2.default)(Component);
}
var sheet = this.jss.createStyleSheet(styles, (0, _extends3.default)({
meta: _meta,
flip: typeof flip === 'boolean' ? flip : theme.direction === 'rtl',
link: false
}, this.sheetOptions, stylesCreatorSaved.options, {
name: name
}, styleSheetOptions));
sheetManagerTheme.sheet = sheet;
sheet.attach();
var sheetsRegistry = this.context[ns.sheetsRegistry];
if (sheetsRegistry) {
sheetsRegistry.add(sheet);
}
}
sheetManagerTheme.refs += 1;
}
}, {
key: 'detach',
value: function detach(theme) {
if (this.disableStylesGeneration) {
return;
}
var stylesCreatorSaved = this.stylesCreatorSaved;
var sheetManager = this.sheetsManager.get(stylesCreatorSaved);
var sheetManagerTheme = sheetManager.get(theme);
sheetManagerTheme.refs -= 1;
if (sheetManagerTheme.refs === 0) {
sheetManager.delete(theme);
this.jss.removeStyleSheet(sheetManagerTheme.sheet);
var sheetsRegistry = this.context[ns.sheetsRegistry];
if (sheetsRegistry) {
sheetsRegistry.remove(sheetManagerTheme.sheet);
}
}
}
}, {
key: 'render',
value: function render() {
var _this3 = this;
var _props = this.props,
classesProp = _props.classes,
innerRef = _props.innerRef,
other = (0, _objectWithoutProperties3.default)(_props, ['classes', 'innerRef']);
var classes = void 0;
var renderedClasses = {};
if (!this.disableStylesGeneration) {
var sheetManager = this.sheetsManager.get(this.stylesCreatorSaved);
var sheetsManagerTheme = sheetManager.get(this.theme);
renderedClasses = sheetsManagerTheme.sheet.classes;
}
if (classesProp) {
classes = (0, _extends3.default)({}, renderedClasses, (0, _keys2.default)(classesProp).reduce(function (accumulator, key) {
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(renderedClasses[key] || _this3.disableStylesGeneration, ['Material-UI: the key `' + key + '` ' + ('provided to the classes property is not implemented in ' + (0, _getDisplayName2.default)(Component) + '.'), 'You can only override one of the following: ' + (0, _keys2.default)(renderedClasses).join(',')].join('\n')) : void 0;
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(!classesProp[key] || typeof classesProp[key] === 'string', ['Material-UI: the key `' + key + '` ' + ('provided to the classes property is not valid for ' + (0, _getDisplayName2.default)(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];
}
return accumulator;
}, {}));
} else {
classes = renderedClasses;
}
var 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 _react2.default.createElement(Component, (0, _extends3.default)({ classes: classes }, more, other, { ref: innerRef }));
}
}]);
return Style;
}(_react2.default.Component);
Style.contextTypes = (0, _extends3.default)({
muiThemeProviderOptions: _propTypes2.default.object
}, _contextTypes2.default, listenToTheme ? _themeListener2.default.contextTypes : {});
Style.Naked = Component;
Style.propTypes = process.env.NODE_ENV !== "production" ? {
classes: require('prop-types').object,
innerRef: require('prop-types').func
} : {};
(0, _hoistNonReactStatics2.default)(Style, Component);
// Higher specificity
Style.options = options;
if (process.env.NODE_ENV !== 'production') {
Style.displayName = (0, _wrapDisplayName2.default)(Component, 'withStyles');
}
return Style;
};
};
exports.default = withStyles;

View File

@@ -0,0 +1,347 @@
// @flow weak
import React from 'react';
import PropTypes from 'prop-types';
import warning from 'warning';
import type { HigherOrderComponent } from 'react-flow-types';
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: Map<*, *> = 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;
}
type Options = {
flip?: boolean,
withTheme?: boolean,
name?: string,
// Problem: https://github.com/brigand/babel-plugin-flow-react-proptypes/issues/127
// import type { StyleSheetFactoryOptions } from 'jss/lib/types';
// ...StyleSheetFactoryOptions,
// and the fact that we currently cannot import/spread types with
// https://github.com/brigand/babel-plugin-flow-react-proptypes/issues/106
media?: string,
meta?: string,
index?: number,
link?: boolean,
element?: HTMLStyleElement,
generateClassName?: Function, // generateClassName - use generic to stop the bleeding.
};
export type RequiredProps = {
/**
* Useful to extend the style applied to components.
*/
classes?: Object,
/**
* Use that property to pass a ref callback to the decorated component.
*/
innerRef?: Function,
};
// Note, theme is conditionally injected, but flow is static analysis so we need to include it.
export type InjectedProps = { classes: Object, theme: Object };
// 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: Object,
options?: Options = {},
): HigherOrderComponent<RequiredProps, InjectedProps> => (Component: any): any => {
const { withTheme = false, flip, name, ...styleSheetOptions } = options;
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<RequiredProps> {
static contextTypes = {
muiThemeProviderOptions: PropTypes.object,
...contextTypes,
...(listenToTheme ? themeListener.contextTypes : {}),
};
// Exposed for tests purposes
static options: ?Options;
// Exposed for test purposes.
static Naked = Component;
constructor(props, context: Object) {
super(props, context);
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 = {
generateClassName,
...this.context[ns.sheetOptions],
};
// We use || as it's lazy evaluated.
this.theme = listenToTheme ? themeListener.initial(context) || getDefaultTheme() : noopTheme;
}
state = {};
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: Object) {
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, {
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: Object) {
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);
}
}
}
unsubscribeId = null;
jss = null;
sheetsManager = sheetsManager;
disableStylesGeneration = false;
stylesCreatorSaved = null;
theme = null;
sheetOptions = null;
theme = null;
render() {
const { classes: classesProp, innerRef, ...other } = this.props;
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 = {
...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 <Component classes={classes} {...more} {...other} ref={innerRef} />;
}
}
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,128 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _wrapDisplayName = require('recompose/wrapDisplayName');
var _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName);
var _createMuiTheme = require('./createMuiTheme');
var _createMuiTheme2 = _interopRequireDefault(_createMuiTheme);
var _themeListener = require('./themeListener');
var _themeListener2 = _interopRequireDefault(_themeListener);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// 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
var babelPluginFlowReactPropTypes_proptype_HigherOrderComponent = require('react-flow-types').babelPluginFlowReactPropTypes_proptype_HigherOrderComponent || require('prop-types').any;
var defaultTheme = void 0;
function getDefaultTheme() {
if (defaultTheme) {
return defaultTheme;
}
defaultTheme = (0, _createMuiTheme2.default)();
return defaultTheme;
}
var babelPluginFlowReactPropTypes_proptype_InjectedProps = {
theme: require('prop-types').object.isRequired
};
// Provide the theme object as a property to the input component.
var withTheme = function withTheme() {
return function (Component) {
var WithTheme = function (_React$Component) {
(0, _inherits3.default)(WithTheme, _React$Component);
function WithTheme(props, context) {
(0, _classCallCheck3.default)(this, WithTheme);
var _this = (0, _possibleConstructorReturn3.default)(this, (WithTheme.__proto__ || (0, _getPrototypeOf2.default)(WithTheme)).call(this, props, context));
_this.state = {};
_this.unsubscribeId = null;
_this.state = {
// We use || as it's lazy evaluated.
theme: _themeListener2.default.initial(context) || getDefaultTheme()
};
return _this;
}
// Exposed for test purposes.
(0, _createClass3.default)(WithTheme, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _this2 = this;
this.unsubscribeId = _themeListener2.default.subscribe(this.context, function (theme) {
_this2.setState({ theme: theme });
});
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
if (this.unsubscribeId !== null) {
_themeListener2.default.unsubscribe(this.context, this.unsubscribeId);
}
}
}, {
key: 'render',
value: function render() {
return _react2.default.createElement(Component, (0, _extends3.default)({ theme: this.state.theme }, this.props));
}
}]);
return WithTheme;
}(_react2.default.Component);
WithTheme.contextTypes = _themeListener2.default.contextTypes;
WithTheme.displayName = (0, _wrapDisplayName2.default)(Component, 'withTheme');
WithTheme.Naked = Component;
return WithTheme;
};
};
exports.default = withTheme;

View File

@@ -0,0 +1,64 @@
// @flow 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 type { HigherOrderComponent } from 'react-flow-types';
import createMuiTheme from './createMuiTheme';
import themeListener from './themeListener';
let defaultTheme;
function getDefaultTheme() {
if (defaultTheme) {
return defaultTheme;
}
defaultTheme = createMuiTheme();
return defaultTheme;
}
export type InjectedProps = { theme: Object };
// Provide the theme object as a property to the input component.
const withTheme = (): HigherOrderComponent<{}, InjectedProps> => (Component: any): any => {
class WithTheme extends React.Component<{}, { theme: Object }> {
static contextTypes = themeListener.contextTypes;
static displayName = wrapDisplayName(Component, 'withTheme');
// Exposed for test purposes.
static Naked = Component;
constructor(props, context) {
super(props, context);
this.state = {
// We use || as it's lazy evaluated.
theme: themeListener.initial(context) || getDefaultTheme(),
};
}
state = {};
componentDidMount() {
this.unsubscribeId = themeListener.subscribe(this.context, theme => {
this.setState({ theme });
});
}
componentWillUnmount() {
if (this.unsubscribeId !== null) {
themeListener.unsubscribe(this.context, this.unsubscribeId);
}
}
unsubscribeId = null;
render() {
return <Component theme={this.state.theme} {...this.props} />;
}
}
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,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
// Needed as the zIndex works with absolute values.
var zIndex = {
mobileStepper: 900,
menu: 1000,
appBar: 1100,
drawerOverlay: 1200,
navDrawer: 1300,
dialogOverlay: 1400,
dialog: 1500,
layer: 2000,
popover: 2100,
snackbar: 2900,
tooltip: 3000
};
exports.default = zIndex;

View File

@@ -0,0 +1,18 @@
// @flow
// 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;