Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // @flow
- import * as React from 'react';
- import PropTypes from 'prop-types';
- const contextTypes = {
- insertCss: PropTypes.func,
- };
- type StylesContextType = KeyValueOfType<Object>;
- const { Provider, Consumer } = React.createContext<StylesContextType>({});
- const getThemeFromContext = <Theme>(id: string, context: StylesContextType): Theme | void => {
- const theme = context[id];
- if (!theme) {
- return;
- }
- return (theme: any);
- };
- type StyleThemeResolverType<Theme, Props> = (Props, Theme | void) => Theme | void;
- type StyleThemeParams<Theme, Props> = {
- id: string,
- styles: Array<Object>,
- resolveTheme?: StyleThemeResolverType<Theme, Props>,
- };
- type StyleThemeProviderType<Theme, Props> = {
- <Props>(Theme): (React.ComponentType<Props>) => React.ComponentType<Props>,
- $$styleThemeId: string,
- $$styleThemeStyles: Array<Object>,
- $$styleThemeResolver: StyleThemeResolverType<Theme, Props>,
- }
- export function createStyleTheme<Theme, Props>(
- { id, styles, resolveTheme }: StyleThemeParams<Theme, Props>,
- ): StyleThemeProviderType<Theme, Props> {
- const defaultResolver = (props, styleTheme) => styleTheme;
- const resolver = resolveTheme || defaultResolver;
- const styleThemeProvider = (theme) => (Component) => (props) => (
- <Consumer>
- {(context) => (
- <Provider value={{ ...context, [id]: theme }}>
- <Component {...props} />
- </Provider>
- )}
- </Consumer>
- );
- styleThemeProvider.$$styleThemeId = id;
- styleThemeProvider.$$styleThemeStyles = styles;
- styleThemeProvider.$$styleThemeResolver = resolver;
- return styleThemeProvider;
- }
- export type StyleThemePropType = {
- s: Object,
- };
- type StylesType<Theme, Props> =
- | CssModuleType
- | StyleThemeProviderType<Theme, Props>;
- function withStyles<Theme: Object, Props: Object>(styles: StylesType<Theme, Props>) {
- let getStyles;
- let resolveStyles: (Props, StylesContextType) => Theme | void;
- if (typeof styles.$$styleThemeResolver === 'function') {
- const resolver = styles.$$styleThemeResolver;
- getStyles = () => styles.$$styleThemeStyles;
- resolveStyles = (props, context) => {
- const stylesTheme = getThemeFromContext(styles.$$styleThemeId, context);
- return resolver(props, stylesTheme);
- };
- } else {
- getStyles = () => [styles];
- resolveStyles = () => {};
- }
- return function wrapWithStyles(
- ComposedComponent: React.ComponentType<Props & StyleThemePropType>,
- ): React.ComponentType<Props> {
- class WithStyles extends React.PureComponent<Props> {
- removeCss: Function;
- constructor(props, context) {
- super(props, context);
- this.removeCss = context.insertCss(...getStyles());
- }
- componentWillUnmount() {
- if (this.removeCss) {
- setTimeout(this.removeCss, 0);
- }
- }
- render() {
- return (
- <Consumer>
- {(context) => {
- const s = resolveStyles(this.props, context);
- return (
- <ComposedComponent s={s} {...this.props} />
- );
- }}
- </Consumer>
- );
- }
- }
- const displayName = ComposedComponent.displayName || ComposedComponent.name || '';
- WithStyles.displayName = `WithStyles(${displayName})`;
- WithStyles.contextTypes = contextTypes;
- return WithStyles;
- };
- }
- export default withStyles;
Add Comment
Please, Sign In to add comment