styletron-inferno/src/styled.js

  1. const createElement = require('inferno-create-element');
  2. const {injectStylePrefixed} = require('styletron-utils');
  3. const {
  4. assign,
  5. isNil,
  6. isObject,
  7. isString,
  8. isFunction
  9. } = require('./utils');
  10. const STYLETRON_KEY = '__STYLETRON';
  11. module.exports = styled;
  12. /**
  13. * Helper function to create styled components
  14. * @packagename styletron-inferno
  15. * @param {string|function} name Tag name or component function/class
  16. * @param {function|object} styles Style object or function that returns a style object
  17. * @return {function} Styled component
  18. *
  19. * @example
  20. * import { styled } from 'styletron-inferno';
  21. *
  22. * const Panel = styled('div', {
  23. * backgroundColor: 'lightblue',
  24. * fontSize: '12px'
  25. * });
  26. *
  27. * <Panel>Hello World</Panel>
  28. *
  29. * @example
  30. * import { styled } from 'styletron-inferno';
  31. *
  32. * const Panel = styled('div', (props) => ({
  33. * backgroundColor: props.alert ? 'orange' : 'lightblue',
  34. * fontSize: '12px'
  35. * }));
  36. *
  37. * <Panel alert>Danger!</Panel>
  38. *
  39. * @example
  40. * import { styled } from 'styletron-inferno';
  41. *
  42. * const DeluxePanel = styled(Panel, (props) => ({
  43. * backgroundColor: props.alert ? 'red' : 'lime',
  44. * boxShadow: '3px 3px 3px darkgray',
  45. * color: 'white'
  46. * }));
  47. *
  48. * <DeluxePanel>Bonjour Monde</DeluxePanel>
  49. */
  50. function styled(name, styles) {
  51. // Styled component
  52. if (name && name.hasOwnProperty(STYLETRON_KEY)) {
  53. const component = name[STYLETRON_KEY];
  54. const stylesArray = component.stylesArray.concat(styles);
  55. return createStyledComponent(component.name, stylesArray);
  56. // Tag name or non-styled component
  57. } else if (isString(name) || isFunction(name)) {
  58. return createStyledComponent(name, [styles]);
  59. }
  60. throw new Error('`styled` takes either a DOM element name or a component');
  61. }
  62. function createStyledComponent(name, stylesArray) {
  63. function StyledComponent(props, context) {
  64. const newProps = assign({}, props);
  65. const styles = resolveStyles(stylesArray, props, context);
  66. const className = injectStylePrefixed(context.styletron, styles);
  67. newProps.className = props.className
  68. ? `${props.className} ${className}`
  69. : className;
  70. if (isFunction(props.innerRef)) {
  71. newProps.ref = props.innerRef;
  72. delete newProps.innerRef;
  73. }
  74. return createElement(name, newProps);
  75. }
  76. StyledComponent[STYLETRON_KEY] = {name, stylesArray};
  77. return StyledComponent;
  78. }
  79. function resolveStyles(stylesArray, props, context) {
  80. const resolvedStyles = {};
  81. for (let i = 0, l = stylesArray.length, styles; i < l; i++) {
  82. styles = stylesArray[i];
  83. if (!isNil(styles)) {
  84. if (isFunction(styles)) {
  85. assign(resolvedStyles, styles(props, context));
  86. } else if (isObject(styles)) {
  87. assign(resolvedStyles, styles);
  88. }
  89. }
  90. }
  91. return resolvedStyles;
  92. }