UnlyEd/next-right-now-admin

View on GitHub
src/utils/css.ts

Summary

Maintainability
A
0 mins
Test Coverage
import * as Sentry from '@sentry/node';
import { createLogger } from '@unly/utils-simple-logger';
import { getPropertyName } from 'css-to-react-native';
import isPlainObject from 'lodash.isplainobject';
import map from 'lodash.map';

const logger = createLogger({
  label: 'utils/css',
});

/**
 * Takes a standard css string and returns an object of {"key": "value"} that is react-compatible
 * Relies on https://github.com/styled-components/css-to-react-native#api to resolve the property name (getPropertyName)
 *
 * @example cssToReactStyle('border-width: 5px; padding: 8px 10px'}); // => {borderWidth: '5px', padding: '8px 10px'}
 *
 * If the given "css" param is an object, it will be returned untouched
 * Any unexpected type/value will return an empty object
 *
 * Doesn't handle meta attributes, such as "&:hover" and alike
 *
 * @param css
 * @return {object}
 */
export const cssToReactStyle = (css: string | object): object => {
  // If object is given, return object (could be react style object mistakenly provided)
  if (isPlainObject(css)) {
    // @ts-ignore
    return css;
  }

  // If falsy, then probably empty string or null, nothing to be done there
  if (!css) {
    return {};
  }

  // Only accepts strings
  if (typeof css !== 'string') {
    const errorMessage = `Unexpected type "${typeof css}" when expecting string, with value "${css}"`;
    Sentry.captureException(Error(errorMessage));
    logger.error(errorMessage, 'cssToReactStyle');
    return {};
  }

  const style = {};
  const rules = css.split(';');
  map(rules, (rule) => {
    let [key, value] = rule.split(':');

    if (key && value) {
      key = key.trim();
      value = value.trim();

      style[getPropertyName(key)] = value;
    } // If either the key or value is falsy, ignore the rule TODO could log error but need to handle special case where string ends with a ";"
  });

  return style;
};