Skip to content

Instantly share code, notes, and snippets.

@tdreyno
Created February 8, 2017 19:08
Show Gist options
  • Save tdreyno/8e1f7448c8be88a483f96752c040097e to your computer and use it in GitHub Desktop.
Save tdreyno/8e1f7448c8be88a483f96752c040097e to your computer and use it in GitHub Desktop.
import {
StyleSheet,
css as stylesheetToClassNames,
} from 'aphrodite';
import { Map } from 'immutable';
const Prefixer = require('inline-style-prefixer');
import { DEVELOPMENT } from '../config';
const prefixer = new Prefixer({ userAgent: navigator.userAgent });
function prefixStyles(obj: Object) {
return prefixer.prefix(obj);
}
export interface IStyleProps {
className?: string;
style?: Object;
}
let knownStylesheets = Map();
export function stylesheet<T>(styles: T): T {
const sheet = StyleSheet.create(styles as any);
for (const key in sheet) {
const originalObject = (styles as any)[key];
knownStylesheets = knownStylesheets.set(originalObject, sheet[key]);
}
return styles;
}
function knownStyle(obj: Object) {
return knownStylesheets.get(obj);
}
export type IPossibleStyle = Object | string | null | undefined | false;
function flattenStyleReducer(sum: any, style: IPossibleStyle) {
if (!style) { return sum; }
return Object.assign(sum, style);
}
function flattenStyles(styles: Array<IPossibleStyle>): Object {
return styles.reduce(flattenStyleReducer, {});
}
// TODO: Find a way to quickly memoize this.
export const css = (...styles: Array<IPossibleStyle>): IStyleProps => {
const fromStylesheet = styles.filter((style: IPossibleStyle) => style && typeof style !== 'string' && knownStyle(style));
const notFromStylesheet = styles.filter((style: IPossibleStyle) => style && typeof style !== 'string' && !knownStyle(style));
const fromClassName = styles.filter((style: IPossibleStyle) => style && typeof style === 'string');
const prefixedInline = notFromStylesheet.map(prefixStyles);
if (DEVELOPMENT) {
let gotInlineStyle = false;
for (const style of styles) {
if (!style) {
continue;
}
if (knownStyle(style) || typeof style === 'string') {
if (gotInlineStyle) {
throw new Error('Tried to add a class-based style AFTER an inline style. Precedence will be confusing. Please refactor');
}
} else {
gotInlineStyle = true;
}
}
// debugger;
return {
style: {
...flattenStyles(fromStylesheet),
...flattenStyles(prefixedInline),
},
...(
fromClassName.length > 0
? {
className: fromClassName.join(' '),
}
: {}),
};
} else {
const classNames = fromClassName.concat([
stylesheetToClassNames(fromStylesheet.map(knownStyle)),
]).join(' ');
return {
...(
classNames.length > 0
? {
className: classNames,
}
: {}),
style: flattenStyles(prefixedInline),
};
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment