CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-radium

A set of tools to manage inline styles on React elements with support for pseudo-classes, media queries, and keyframe animations.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

plugins.mddocs/

Plugin System

Extensible plugin architecture that allows customization of Radium's style processing behavior through a modular system of processing functions.

Capabilities

Plugin Interface

Plugins are functions that process style objects and return modifications to component props, styles, or global state.

/**
 * Plugin function interface
 * @param config - Plugin configuration object with utilities and current state
 * @returns Plugin result with optional modifications to component
 */
interface Plugin {
  (config: PluginConfig): PluginResult | void;
}

interface PluginConfig {
  /** Component name (may not be available if minified) */
  componentName: string;
  /** Current Radium configuration */
  config: RadiumConfig;
  /** Current element props (can be modified by previous plugins) */
  props: object;
  /** Current element style (can be modified by previous plugins) */
  style: object;
  
  // Utility functions
  /** Add CSS to global stylesheet */
  addCSS: (css: string) => { remove: () => void };
  /** Add !important to all values in style object */
  appendImportantToEachValue: (style: object) => object;
  /** Convert CSS rules object to string */
  cssRuleSetToString: (selector: string, rules: object, userAgent?: string) => string;
  /** Get component field value */
  getComponentField: (key: string) => any;
  /** Get global state value */
  getGlobalState: (key: string) => any;
  /** Get element state (hover, focus, active) */
  getState: (stateKey: string, elementKey?: string) => any;
  /** Generate hash from string */
  hash: (data: string) => string;
  /** Check if value is nested style object */
  isNestedStyle: (value: any) => boolean;
  /** Merge array of style objects */
  mergeStyles: (styles: object[]) => object;
  /** Set component state */
  setState: (stateKey: string, value: any, elementKey?: string) => void;
  /** Environment detection utilities */
  ExecutionEnvironment: {
    canUseEventListeners: boolean;
    canUseDOM: boolean;
  };
}

interface PluginResult {
  /** Fields to merge into component instance */
  componentFields?: object;
  /** Values to merge into global state */
  globalState?: object;
  /** Props to merge into element */
  props?: object;
  /** Style object to replace current style */
  style?: object;
}

Built-in Plugins

Radium includes a comprehensive set of built-in plugins that handle core functionality.

interface BuiltinPlugins {
  /** Validates style properties and detects common issues */
  checkProps: Plugin;
  /** Processes keyframe animation objects */
  keyframes: Plugin;
  /** Merges arrays of style objects intelligently */
  mergeStyleArray: Plugin;
  /** Adds vendor prefixes to CSS properties */
  prefix: Plugin;
  /** Extracts nested style objects for processing */
  removeNestedStyles: Plugin;
  /** Handles :hover, :focus, :active pseudo-classes */
  resolveInteractionStyles: Plugin;
  /** Processes @media query styles */
  resolveMediaQueries: Plugin;
  /** Handles :visited pseudo-class styles */
  visited: Plugin;
}

Usage Examples:

import Radium from 'radium';

// Access built-in plugins
const { Plugins } = Radium;

// Default plugin order
const defaultPlugins = [
  Plugins.mergeStyleArray,
  Plugins.checkProps,
  Plugins.resolveMediaQueries,
  Plugins.resolveInteractionStyles,
  Plugins.keyframes,
  Plugins.visited,
  Plugins.removeNestedStyles,
  Plugins.prefix,
  Plugins.checkProps // Run again after processing
];

Custom Plugins

Create custom plugins to extend Radium's functionality.

Usage Examples:

// Simple logging plugin
function loggingPlugin({ componentName, style }) {
  console.log(`Styling component: ${componentName}`, style);
  // Return nothing - no modifications
}

// Style transformation plugin
function uppercaseTextPlugin({ style }) {
  if (style.textTransform === 'uppercase-all') {
    return {
      style: {
        ...style,
        textTransform: 'uppercase',
        fontWeight: 'bold',
        letterSpacing: '1px'
      }
    };
  }
}

// Plugin that adds CSS to global stylesheet
function globalStylesPlugin({ addCSS, hash }) {
  const css = `
    .custom-utility {
      display: flex;
      align-items: center;
      justify-content: center;
    }
  `;
  
  const id = hash(css);
  if (!document.getElementById(id)) {
    const { remove } = addCSS(css);
    // Store remove function if needed later
  }
}

// Use custom plugins
const MyComponent = Radium({
  plugins: [
    Plugins.mergeStyleArray,
    loggingPlugin,
    uppercaseTextPlugin,
    Plugins.checkProps,
    Plugins.resolveMediaQueries,
    Plugins.resolveInteractionStyles,
    globalStylesPlugin,
    Plugins.prefix,
    Plugins.checkProps
  ]
})(BaseComponent);

Plugin Execution Order

Plugins are executed in the order they appear in the configuration array. Each plugin receives the result of previous plugins.

Usage Examples:

// Plugin execution order matters
const orderedPlugins = [
  // 1. First, merge style arrays
  Plugins.mergeStyleArray,
  
  // 2. Validate initial styles
  Plugins.checkProps,
  
  // 3. Process special style objects that create new styles
  Plugins.resolveMediaQueries,
  Plugins.resolveInteractionStyles,
  Plugins.keyframes,
  Plugins.visited,
  
  // 4. Extract nested styles
  Plugins.removeNestedStyles,
  
  // 5. Add vendor prefixes
  Plugins.prefix,
  
  // 6. Final validation
  Plugins.checkProps
];

Plugin Development

Guidelines for developing custom plugins.

/**
 * Plugin development template
 */
function customPlugin({
  componentName,
  config,
  props,
  style,
  addCSS,
  getState,
  setState,
  isNestedStyle,
  mergeStyles
}) {
  // 1. Check if plugin should run
  if (!shouldProcessStyle(style)) {
    return; // No modifications
  }
  
  // 2. Process style object
  const processedStyle = processStyle(style);
  
  // 3. Add any necessary CSS
  if (needsGlobalCSS(processedStyle)) {
    addCSS(generateCSS(processedStyle));
  }
  
  // 4. Return modifications
  return {
    style: processedStyle,
    props: {
      ...props,
      'data-processed': true
    }
  };
}

Usage Examples:

// Responsive utilities plugin
function responsiveUtilitiesPlugin({ style, addCSS, hash }) {
  const responsiveProps = ['responsiveWidth', 'responsiveHeight'];
  const hasResponsiveProps = responsiveProps.some(prop => style[prop]);
  
  if (!hasResponsiveProps) return;
  
  const newStyle = { ...style };
  
  if (style.responsiveWidth) {
    const breakpoints = style.responsiveWidth;
    Object.keys(breakpoints).forEach(breakpoint => {
      const css = `
        @media (min-width: ${breakpoint}) {
          .responsive-width-${hash(breakpoint)} {
            width: ${breakpoints[breakpoint]};
          }
        }
      `;
      addCSS(css);
    });
    
    newStyle.className = `responsive-width-${hash(JSON.stringify(breakpoints))}`;
    delete newStyle.responsiveWidth;
  }
  
  return { style: newStyle };
}

Plugin Configuration

Plugins can be configured globally or per-component.

Usage Examples:

// Global plugin configuration
const GlobalRadium = Radium({
  plugins: [
    ...Radium.Plugins,
    customPlugin
  ]
});

// Per-component configuration
const SpecialComponent = Radium({
  plugins: [
    Plugins.mergeStyleArray,
    specialComponentPlugin,
    Plugins.prefix
  ]
})(BaseComponent);

// Runtime configuration via props
<MyComponent
  radiumConfig={{
    plugins: [...customPlugins]
  }}
/>

Built-in Plugin Details

mergeStyleArray

Intelligently merges arrays of style objects with deep merging for nested styles.

interface MergeStyleArrayPlugin {
  /** Processes style arrays into single style object */
  (config: PluginConfig): PluginResult;
}

checkProps

Validates style properties and usage patterns, warning about common issues.

interface CheckPropsPlugin {
  /** Validates style objects and usage patterns */
  (config: PluginConfig): void;
}

resolveMediaQueries

Processes @media query styles and applies them based on current media conditions.

interface ResolveMediaQueriesPlugin {
  /** Processes @media query styles */
  (config: PluginConfig): PluginResult;
}

resolveInteractionStyles

Handles :hover, :focus, and :active pseudo-class styles by setting up event listeners.

interface ResolveInteractionStylesPlugin {
  /** Handles pseudo-class styles */
  (config: PluginConfig): PluginResult;
}

prefix

Adds vendor prefixes to CSS properties and values based on browser detection.

interface PrefixPlugin {
  /** Adds vendor prefixes to styles */
  (config: PluginConfig): PluginResult;
}

Types

interface Plugin {
  (config: PluginConfig): PluginResult | void;
}

interface PluginConfig {
  componentName: string;
  config: RadiumConfig;
  props: object;
  style: object;
  addCSS: (css: string) => { remove: () => void };
  appendImportantToEachValue: (style: object) => object;
  cssRuleSetToString: (selector: string, rules: object, userAgent?: string) => string;
  getComponentField: (key: string) => any;
  getGlobalState: (key: string) => any;
  getState: (stateKey: string, elementKey?: string) => any;
  hash: (data: string) => string;
  isNestedStyle: (value: any) => boolean;
  mergeStyles: (styles: object[]) => object;
  setState: (stateKey: string, value: any, elementKey?: string) => void;
  ExecutionEnvironment: {
    canUseEventListeners: boolean;
    canUseDOM: boolean;
  };
}

interface PluginResult {
  componentFields?: object;
  globalState?: object;
  props?: object;
  style?: object;
}

Install with Tessl CLI

npx tessl i tessl/npm-radium

docs

component-enhancement.md

index.md

keyframes.md

plugins.md

state-management.md

style-components.md

tile.json