npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, πŸ‘‹, I’m Ryan HefnerΒ  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you πŸ™

Β© 2024 – Pkg Stats / Ryan Hefner

class-glue

v1.14.1

Published

Dynamic class name generation made easy with a lightweight utility to simplify styling in React, React Native, and more. No fuss, just class names! πŸ’…βœ¨

Downloads

366

Readme

class-glue πŸ’«

npm version npm downloads bundle size License: MIT PRs Welcome Release Build Sponsor

A lightweight (< 450B) yet powerful utility for dynamic class name generation in JavaScript applications. Perfect for React, React Native, Vue.js, and any JavaScript project where you need flexible class name handling with type safety.

Introduction

class-glue solves the common challenge of managing dynamic class names in modern web applications. Whether you're toggling classes based on state, merging CSS modules, or handling complex conditional styling, class-glue provides an elegant and performant solution.

Why class-glue?

  • πŸͺΆ Lightweight: Entire core is just 425B (minified + gzipped), with modular utilities each under 540B
  • πŸ” Type-Safe: Built with TypeScript for robust type checking and excellent IDE support
  • 🌐 Framework Agnostic: Works seamlessly with React, React Native/Expo, Vue, Angular, or vanilla JavaScript
  • 🧩 Modular Design: Import only what you need - each utility can be used standalone
  • 🎯 Zero Dependencies: No external dependencies means no bloat in your project
  • 🌳 Tree-Shakeable: Modern bundlers can eliminate unused code for optimal bundle size
  • ⚑ Performance Focused: Optimized internals with minimal runtime overhead

Core Features

🎯 Multiple API Styles

  • Main API (class-glue): Full-featured class name generation
  • String Only (join-strings): Optimized for simple string concatenation
  • Object Keys (keys-to-strings): Efficient object-based class generation
  • CSS Modules (merge-module-strings): First-class CSS Modules support
  • Style Objects (merge-styles): React Native and style object handling

πŸ’‘ Smart Type System

  • Full TypeScript support with detailed type definitions
  • Intelligent type inference for better development experience
  • Strict type checking to catch errors early

πŸ›  Developer Experience

  • Comprehensive source maps for easy debugging
  • Detailed error messages in development
  • Extensive documentation with real-world examples

πŸ”‹ Production Ready

  • Thoroughly tested with 100% coverage
  • Used in production by numerous projects
  • Active maintenance and community support

Quick Examples

Basic Usage

import classGlue from 'class-glue';

classGlue('btn', { active: true }, ['primary']);
// => 'btn active primary'

String-Only Operations

import classGlueString from 'class-glue/join-strings';

classGlueString('card', isActive && 'card-active');
// => 'card card-active' (if isActive is true)

Object-Based Operations

import keysToStrings from 'class-glue/keys-to-strings';

keysToStrings({
  btn: true,
  'btn-active': isActive
});
// => 'btn btn-active' (if isActive is true)

CSS Modules Support

import createModuleGlue from 'class-glue/merge-module-strings';
import styles from './Button.module.css';

const moduleGlue = createModuleGlue(styles);
moduleGlue('button', { active: isActive });
// => 'Button_button_x7d Button_active_d4f'

React Native Style Handling

import createStyleGlue from 'class-glue/merge-styles';

const styleGlue = createStyleGlue({
  base: { padding: 10 },
  active: { backgroundColor: 'blue' }
});
styleGlue('base', { active: isActive });
// => { padding: 10, backgroundColor: 'blue' }

Installation

Package Managers

NPM

npm install class-glue

Yarn

yarn add class-glue

PNPM

pnpm add class-glue

Bun

bun add class-glue

CDN Usage

<!-- Global: window.classG -->
<script src="https://unpkg.com/class-glue"></script>

<!-- Individual utilities -->
<script src="https://unpkg.com/class-glue/dist/umd/join-strings.min.js"></script>        <!-- window.classGJoinStrings -->
<script src="https://unpkg.com/class-glue/dist/umd/keys-to-strings.min.js"></script>     <!-- window.classGKeysToStrings -->
<script src="https://unpkg.com/class-glue/dist/umd/merge-module-strings.min.js"></script> <!-- window.classGMergeModuleStrings -->
<script src="https://unpkg.com/class-glue/dist/umd/merge-styles.min.js"></script>        <!-- window.classGMergeStyles -->

When using via CDN, the utilities are available as:

  • window.classG (main)
  • window.classGJoinStrings
  • window.classGKeysToStrings
  • window.classGMergeModuleStrings
  • window.classGMergeStyles

Import Formats

class-glue ships with multiple build formats:

| Format | Entry Point | Usage | | --- | --- | --- | | CommonJS | dist/index.js | Node.js, Webpack, etc. | | ES Module | dist/esm/index.js | Modern bundlers | | UMD | dist/umd/index.min.js | Direct browser usage |

Each utility is available in all formats above. Import the one that best suits your needs:

// ES Modules (Recommended)
import classGlue from 'class-glue';

// CommonJS
const classGlue = require('class-glue');

// Individual utilities
import joinStrings from 'class-glue/join-strings';
import keysToStrings from 'class-glue/keys-to-strings';
import createModuleGlue from 'class-glue/merge-module-strings';
import createStyleGlue from 'class-glue/merge-styles';

Usage Examples

Basic Usage Example

import classGlue from 'class-glue';

// Simple strings
classGlue('btn', 'primary');  // => 'btn primary'

// Conditionals
classGlue('btn', {
  'btn-primary': true,
  'btn-disabled': false
});  // => 'btn btn-primary'

// Arrays
classGlue('btn', ['primary', 'disabled']);  // => 'btn primary disabled'

// Ignored values
classGlue('btn', undefined, null, false);  // => 'btn'

// Mixed values (strings, objects, arrays, etc.)
classGlue('btn', 'primary', { active: true }, ['disabled']);  // => 'btn primary active disabled'

React Integration

import classGlue from 'class-glue';

function Button({ isActive, isDisabled, size, children }) {
  return (
    <button
      className={classGlue(
        'btn',
        {
          'btn-active': isActive,
          'btn-disabled': isDisabled,
        },
        size && `btn-${size}`
      )}
    >
      {children}
    </button>
  );
}

CSS Modules

import createModuleGlue from 'class-glue/merge-module-strings';
import styles from './Card.module.css';

const clgl = createModuleGlue(styles);

function Card({ isHighlighted }) {
  return (
    <div className={clgl('card', { cardHighlighted: isHighlighted })}>
      {/* Resolves to actual CSS Module classes like "Card_card_x7d Card_cardHighlighted_f3j" */}
    </div>
  );
}

Style Objects (React Native)

import createStyleGlue from 'class-glue/merge-styles';

const styles = {
  container: { padding: 16, borderRadius: 8 },
  active: { backgroundColor: 'blue' },
  disabled: { opacity: 0.5 }
};

const clgl = createStyleGlue(styles);

function Card({ isActive, isDisabled }) {
  return (
    <View style={clgl('container', {
      active: isActive,
      disabled: isDisabled
    })}>
      {/* Merges styles based on conditions */}
    </View>
  );
}

Conditional Classes

import keysToStrings from 'class-glue/keys-to-strings';

// Object syntax for multiple conditions
keysToStrings({
  base: true,                    // always included
  active: isActive,              // included if isActive is true
  disabled: isDisabled,          // included if isDisabled is true
  [`size-${size}`]: size,       // included if size is truthy
  [styles.custom]: hasCustom     // CSS Module class names work too
});

TypeScript Usage

import classGlue from 'class-glue';
import type { ClassValue } from 'class-glue';

// All utilities are fully typed
function Button<T extends string>({ className, variant }: {
  className?: ClassValue;
  variant?: T;
}) {
  return (
    <button
      className={classGlue(
        'btn',
        className,           // safely accepts ClassValue type
        variant && `btn-${variant}`
      )}
    />
  );
}

API Reference

class-glue (Main)

import classGlue from 'class-glue';

classGlue(...args: ClassValue[]): string;

type ClassValue =
  | string
  | number
  | boolean
  | undefined
  | null
  | { [key: string]: boolean | undefined | null }
  | ClassValue[];

// Full featured class name generation
classGlue(
  'string',           // plain strings
  { active: true },   // object keys with boolean values
  ['array', 'of', 'classes'],  // arrays
  undefined,          // ignored
  null,              // ignored
  false              // ignored
);

join-strings

import joinStrings from 'class-glue/join-strings';

joinStrings(...args: Array<string | undefined | null | boolean>): string;

// Optimized for string-only operations
joinStrings(
  'button',
  isActive && 'active',    // conditional strings
  undefined,               // ignored
  null,                    // ignored
  isPrimary && 'primary'
);

keys-to-strings

import keysToStrings from 'class-glue/keys-to-strings';

keysToStrings(obj: { [key: string]: boolean | undefined | null }): string;

// Efficient object-based class generation
keysToStrings({
  btn: true,              // always included
  'btn-primary': isPrimary,  // included if isPrimary is true
  'btn-active': isActive,    // included if isActive is true
  'btn-disabled': false      // never included
});

merge-module-strings

import createModuleGlue from 'class-glue/merge-module-strings';
import type { ClassValue } from 'class-glue';

createModuleGlue(styleModule: { [key: string]: string }): 
  (...args: ClassValue[]) => string;

// CSS Modules integration
import styles from './Button.module.css';
const clgl = createModuleGlue(styles);

clgl(
  'button',           // looks up 'button' in styles object
  { active: true },   // looks up 'active' in styles object
  styles.custom      // used as-is
);

merge-styles

import createStyleGlue from 'class-glue/merge-styles';
import type { ClassValue } from 'class-glue';

createStyleGlue(styles: { [key: string]: any }): 
  (...args: ClassValue[]) => { [key: string]: any };

// Style object merging (React Native)
const styles = {
  base: { padding: 16 },
  active: { backgroundColor: 'blue' }
};
const clgl = createStyleGlue(styles);

clgl(
  'base',             // includes base styles
  { active: true },   // merges active styles
  customStyles       // merges custom styles
);

Each utility is designed for specific use cases:

  • class-glue: Full-featured, handles all types
  • join-strings: Optimized for string-only operations
  • keys-to-strings: Efficient object-based class generation
  • merge-module-strings: CSS Modules integration
  • merge-styles: Style object merging (React Native)

Contributing

Contributions are always welcome! Please read the contribution guidelines before getting started.

Reporting Issues

If you encounter any issues while using class-glue, please open an issue on the GitHub repository. Make sure to include a clear description, steps to reproduce the issue, and any relevant code snippets or error messages.

Author

Support

If you find class-glue useful, please consider:

  • Starring the repository ⭐
  • Supporting the project πŸ’–
  • Contributing to the project 🀝
  • Sharing your feedback and ideas πŸ’­
  • Referring to the project in your blog posts or articles πŸ“
  • Sharing the project with your friends and colleagues πŸ‘«

Thank you for your support! πŸ™

Acknowledgements

class-glue is inspired by clsx, but with added features for TypeScript, CSS Modules, and React Native styles.

License

MIT Β© Rahul Shetty