{"id":51777350,"url":"https://github.com/shettayyy/class-glue","last_synced_at":"2026-07-20T07:04:11.094Z","repository":{"id":238290332,"uuid":"796259670","full_name":"shettayyy/class-glue","owner":"shettayyy","description":"Dynamic class name generation made easy with a lightweight utility to simplify styling in React, React Native, and more. No fuss, just class names! 💅✨","archived":false,"fork":false,"pushed_at":"2025-01-31T18:35:40.000Z","size":238,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-30T02:07:15.799Z","etag":null,"topics":["classes","classname","classnames","css","html","react","react-native","string","style","styles","stylesheet"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shettayyy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["shettayyy"]}},"created_at":"2024-05-05T12:28:49.000Z","updated_at":"2025-01-10T00:40:26.000Z","dependencies_parsed_at":"2024-08-22T00:11:18.751Z","dependency_job_id":"f424d3a7-b2ed-4f35-a985-9f5a52d4b1c7","html_url":"https://github.com/shettayyy/class-glue","commit_stats":null,"previous_names":["shettayyy/class-x","shettayyy/class-glue","shettayyy/class-y"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/shettayyy/class-glue","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shettayyy%2Fclass-glue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shettayyy%2Fclass-glue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shettayyy%2Fclass-glue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shettayyy%2Fclass-glue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shettayyy","download_url":"https://codeload.github.com/shettayyy/class-glue/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shettayyy%2Fclass-glue/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35676377,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"ssl_error","status_checked_at":"2026-07-20T02:08:09.736Z","response_time":111,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["classes","classname","classnames","css","html","react","react-native","string","style","styles","stylesheet"],"created_at":"2026-07-20T07:04:10.327Z","updated_at":"2026-07-20T07:04:11.089Z","avatar_url":"https://github.com/shettayyy.png","language":"TypeScript","funding_links":["https://github.com/sponsors/shettayyy"],"categories":[],"sub_categories":[],"readme":"# class-glue 💫\n\n[![npm version](https://img.shields.io/npm/v/class-glue.svg?style=flat)](https://www.npmjs.com/package/class-glue) [![npm downloads](https://img.shields.io/npm/d18m/class-glue.svg?style=flat)](https://www.npmjs.com/package/class-glue) [![bundle size](https://img.shields.io/bundlephobia/minzip/class-glue?label=bundle%20size)](https://bundlephobia.com/package/class-glue) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) [![Release](https://github.com/shettayyy/class-glue/actions/workflows/release.yml/badge.svg)](https://github.com/shettayyy/class-glue/actions/workflows/release.yml) [![Build](https://github.com/shettayyy/class-glue/actions/workflows/pr-checks.yml/badge.svg)](https://github.com/shettayyy/class-glue/actions/workflows/pr-checks.yml) [![Sponsor](https://img.shields.io/static/v1?label=Sponsor\u0026message=%E2%9D%A4\u0026logo=GitHub\u0026color=%23fe8e86)](https://github.com/sponsors/shettayyy)\n\n\u003e A lightweight (\u003c 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.\n\n## Introduction\n\nclass-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.\n\n### Why class-glue?\n\n- 🪶 **Lightweight**: Entire core is just 425B (minified + gzipped), with modular utilities each under 540B\n- 🔍 **Type-Safe**: Built with TypeScript for robust type checking and excellent IDE support\n- 🌐 **Framework Agnostic**: Works seamlessly with React, React Native/Expo, Vue, Angular, or vanilla JavaScript\n- 🧩 **Modular Design**: Import only what you need - each utility can be used standalone\n- 🎯 **Zero Dependencies**: No external dependencies means no bloat in your project\n- 🌳 **Tree-Shakeable**: Modern bundlers can eliminate unused code for optimal bundle size\n- ⚡ **Performance Focused**: Optimized internals with minimal runtime overhead\n\n### Core Features\n\n#### 🎯 Multiple API Styles\n\n- **Main API** (`class-glue`): Full-featured class name generation\n- **String Only** (`join-strings`): Optimized for simple string concatenation\n- **Object Keys** (`keys-to-strings`): Efficient object-based class generation\n- **CSS Modules** (`merge-module-strings`): First-class CSS Modules support\n- **Style Objects** (`merge-styles`): React Native and style object handling\n\n#### 💡 Smart Type System\n\n- Full TypeScript support with detailed type definitions\n- Intelligent type inference for better development experience\n- Strict type checking to catch errors early\n\n#### 🛠 Developer Experience\n\n- Comprehensive source maps for easy debugging\n- Detailed error messages in development\n- Extensive documentation with real-world examples\n\n#### 🔋 Production Ready\n\n- Thoroughly tested with 100% coverage\n- Used in production by numerous projects\n- Active maintenance and community support\n\n### Quick Examples\n\n#### Basic Usage\n\n```typescript\nimport classGlue from 'class-glue';\n\nclassGlue('btn', { active: true }, ['primary']);\n// =\u003e 'btn active primary'\n```\n\n#### String-Only Operations\n\n```typescript\nimport classGlueString from 'class-glue/join-strings';\n\nclassGlueString('card', isActive \u0026\u0026 'card-active');\n// =\u003e 'card card-active' (if isActive is true)\n```\n\n#### Object-Based Operations\n\n```typescript\nimport keysToStrings from 'class-glue/keys-to-strings';\n\nkeysToStrings({\n  btn: true,\n  'btn-active': isActive\n});\n// =\u003e 'btn btn-active' (if isActive is true)\n```\n\n#### CSS Modules Support\n\n```typescript\nimport createModuleGlue from 'class-glue/merge-module-strings';\nimport styles from './Button.module.css';\n\nconst moduleGlue = createModuleGlue(styles);\nmoduleGlue('button', { active: isActive });\n// =\u003e 'Button_button_x7d Button_active_d4f'\n```\n\n#### React Native Style Handling\n\n```typescript\nimport createStyleGlue from 'class-glue/merge-styles';\n\nconst styleGlue = createStyleGlue({\n  base: { padding: 10 },\n  active: { backgroundColor: 'blue' }\n});\nstyleGlue('base', { active: isActive });\n// =\u003e { padding: 10, backgroundColor: 'blue' }\n```\n\n## Installation\n\n### Package Managers\n\n#### NPM\n\n```bash copy\nnpm install class-glue\n```\n\n#### Yarn\n\n```bash copy\nyarn add class-glue\n```\n\n#### PNPM\n\n```bash copy\npnpm add class-glue\n```\n\n#### Bun\n\n```bash copy\nbun add class-glue\n```\n\n### CDN Usage\n\n```html\n\u003c!-- Global: window.classG --\u003e\n\u003cscript src=\"https://unpkg.com/class-glue\"\u003e\u003c/script\u003e\n\n\u003c!-- Individual utilities --\u003e\n\u003cscript src=\"https://unpkg.com/class-glue/dist/umd/join-strings.min.js\"\u003e\u003c/script\u003e        \u003c!-- window.classGJoinStrings --\u003e\n\u003cscript src=\"https://unpkg.com/class-glue/dist/umd/keys-to-strings.min.js\"\u003e\u003c/script\u003e     \u003c!-- window.classGKeysToStrings --\u003e\n\u003cscript src=\"https://unpkg.com/class-glue/dist/umd/merge-module-strings.min.js\"\u003e\u003c/script\u003e \u003c!-- window.classGMergeModuleStrings --\u003e\n\u003cscript src=\"https://unpkg.com/class-glue/dist/umd/merge-styles.min.js\"\u003e\u003c/script\u003e        \u003c!-- window.classGMergeStyles --\u003e\n```\n\n\u003e When using via CDN, the utilities are available as:\n\u003e\n\u003e - `window.classG` (main)\n\u003e - `window.classGJoinStrings`\n\u003e - `window.classGKeysToStrings`\n\u003e - `window.classGMergeModuleStrings`\n\u003e - `window.classGMergeStyles`\n\n### Import Formats\n\nclass-glue ships with multiple build formats:\n\n| Format | Entry Point | Usage |\n| --- | --- | --- |\n| CommonJS | `dist/index.js` | Node.js, Webpack, etc. |\n| ES Module | `dist/esm/index.js` | Modern bundlers |\n| UMD | `dist/umd/index.min.js` | Direct browser usage |\n\nEach utility is available in all formats above. Import the one that best suits your needs:\n\n```typescript copy\n// ES Modules (Recommended)\nimport classGlue from 'class-glue';\n\n// CommonJS\nconst classGlue = require('class-glue');\n\n// Individual utilities\nimport joinStrings from 'class-glue/join-strings';\nimport keysToStrings from 'class-glue/keys-to-strings';\nimport createModuleGlue from 'class-glue/merge-module-strings';\nimport createStyleGlue from 'class-glue/merge-styles';\n```\n\n## Usage Examples\n\n### Basic Usage Example\n\n```typescript copy\nimport classGlue from 'class-glue';\n\n// Simple strings\nclassGlue('btn', 'primary');  // =\u003e 'btn primary'\n\n// Conditionals\nclassGlue('btn', {\n  'btn-primary': true,\n  'btn-disabled': false\n});  // =\u003e 'btn btn-primary'\n\n// Arrays\nclassGlue('btn', ['primary', 'disabled']);  // =\u003e 'btn primary disabled'\n\n// Ignored values\nclassGlue('btn', undefined, null, false);  // =\u003e 'btn'\n\n// Mixed values (strings, objects, arrays, etc.)\nclassGlue('btn', 'primary', { active: true }, ['disabled']);  // =\u003e 'btn primary active disabled'\n```\n\n### React Integration\n\n```tsx copy\nimport classGlue from 'class-glue';\n\nfunction Button({ isActive, isDisabled, size, children }) {\n  return (\n    \u003cbutton\n      className={classGlue(\n        'btn',\n        {\n          'btn-active': isActive,\n          'btn-disabled': isDisabled,\n        },\n        size \u0026\u0026 `btn-${size}`\n      )}\n    \u003e\n      {children}\n    \u003c/button\u003e\n  );\n}\n```\n\n### CSS Modules\n\n```tsx copy\nimport createModuleGlue from 'class-glue/merge-module-strings';\nimport styles from './Card.module.css';\n\nconst clgl = createModuleGlue(styles);\n\nfunction Card({ isHighlighted }) {\n  return (\n    \u003cdiv className={clgl('card', { cardHighlighted: isHighlighted })}\u003e\n      {/* Resolves to actual CSS Module classes like \"Card_card_x7d Card_cardHighlighted_f3j\" */}\n    \u003c/div\u003e\n  );\n}\n```\n\n### Style Objects (React Native)\n\n```tsx copy\nimport createStyleGlue from 'class-glue/merge-styles';\n\nconst styles = {\n  container: { padding: 16, borderRadius: 8 },\n  active: { backgroundColor: 'blue' },\n  disabled: { opacity: 0.5 }\n};\n\nconst clgl = createStyleGlue(styles);\n\nfunction Card({ isActive, isDisabled }) {\n  return (\n    \u003cView style={clgl('container', {\n      active: isActive,\n      disabled: isDisabled\n    })}\u003e\n      {/* Merges styles based on conditions */}\n    \u003c/View\u003e\n  );\n}\n```\n\n### Conditional Classes\n\n```typescript copy\nimport keysToStrings from 'class-glue/keys-to-strings';\n\n// Object syntax for multiple conditions\nkeysToStrings({\n  base: true,                    // always included\n  active: isActive,              // included if isActive is true\n  disabled: isDisabled,          // included if isDisabled is true\n  [`size-${size}`]: size,       // included if size is truthy\n  [styles.custom]: hasCustom     // CSS Module class names work too\n});\n```\n\n### TypeScript Usage\n\n```typescript copy\nimport classGlue from 'class-glue';\nimport type { ClassValue } from 'class-glue';\n\n// All utilities are fully typed\nfunction Button\u003cT extends string\u003e({ className, variant }: {\n  className?: ClassValue;\n  variant?: T;\n}) {\n  return (\n    \u003cbutton\n      className={classGlue(\n        'btn',\n        className,           // safely accepts ClassValue type\n        variant \u0026\u0026 `btn-${variant}`\n      )}\n    /\u003e\n  );\n}\n```\n\n## API Reference\n\n### class-glue (Main)\n\n```typescript copy\nimport classGlue from 'class-glue';\n\nclassGlue(...args: ClassValue[]): string;\n\ntype ClassValue =\n  | string\n  | number\n  | boolean\n  | undefined\n  | null\n  | { [key: string]: boolean | undefined | null }\n  | ClassValue[];\n\n// Full featured class name generation\nclassGlue(\n  'string',           // plain strings\n  { active: true },   // object keys with boolean values\n  ['array', 'of', 'classes'],  // arrays\n  undefined,          // ignored\n  null,              // ignored\n  false              // ignored\n);\n```\n\n### join-strings\n\n```typescript copy\nimport joinStrings from 'class-glue/join-strings';\n\njoinStrings(...args: Array\u003cstring | undefined | null | boolean\u003e): string;\n\n// Optimized for string-only operations\njoinStrings(\n  'button',\n  isActive \u0026\u0026 'active',    // conditional strings\n  undefined,               // ignored\n  null,                    // ignored\n  isPrimary \u0026\u0026 'primary'\n);\n```\n\n### keys-to-strings\n\n```typescript copy\nimport keysToStrings from 'class-glue/keys-to-strings';\n\nkeysToStrings(obj: { [key: string]: boolean | undefined | null }): string;\n\n// Efficient object-based class generation\nkeysToStrings({\n  btn: true,              // always included\n  'btn-primary': isPrimary,  // included if isPrimary is true\n  'btn-active': isActive,    // included if isActive is true\n  'btn-disabled': false      // never included\n});\n```\n\n### merge-module-strings\n\n```typescript copy\nimport createModuleGlue from 'class-glue/merge-module-strings';\nimport type { ClassValue } from 'class-glue';\n\ncreateModuleGlue(styleModule: { [key: string]: string }): \n  (...args: ClassValue[]) =\u003e string;\n\n// CSS Modules integration\nimport styles from './Button.module.css';\nconst clgl = createModuleGlue(styles);\n\nclgl(\n  'button',           // looks up 'button' in styles object\n  { active: true },   // looks up 'active' in styles object\n  styles.custom      // used as-is\n);\n```\n\n### merge-styles\n\n```typescript copy\nimport createStyleGlue from 'class-glue/merge-styles';\nimport type { ClassValue } from 'class-glue';\n\ncreateStyleGlue(styles: { [key: string]: any }): \n  (...args: ClassValue[]) =\u003e { [key: string]: any };\n\n// Style object merging (React Native)\nconst styles = {\n  base: { padding: 16 },\n  active: { backgroundColor: 'blue' }\n};\nconst clgl = createStyleGlue(styles);\n\nclgl(\n  'base',             // includes base styles\n  { active: true },   // merges active styles\n  customStyles       // merges custom styles\n);\n```\n\nEach utility is designed for specific use cases:\n\n- `class-glue`: Full-featured, handles all types\n- `join-strings`: Optimized for string-only operations\n- `keys-to-strings`: Efficient object-based class generation\n- `merge-module-strings`: CSS Modules integration\n- `merge-styles`: Style object merging (React Native)\n\n## Contributing\n\nContributions are always welcome! Please read the [contribution guidelines](CONTRIBUTING.md) before getting started.\n\n## Reporting Issues\n\nIf you encounter any issues while using class-glue, please open an issue on the [GitHub repository](https://github.com/shettayyy/class-glue/issues/new/choose). Make sure to include a clear description, steps to reproduce the issue, and any relevant code snippets or error messages.\n\n## Author\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://github.com/shettayyy\" target=\"_blank\"\u003e\n        \u003cimg width=\"160\" height=\"160\" src=\"https://github.com/shettayyy.png?size=160\" style=\"border-radius: 50%;\" alt=\"Rahul Shetty\" /\u003e\n      \u003c/a\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003cdiv\u003e\u003cstrong\u003eRahul Shetty\u003c/strong\u003e\u003c/div\u003e\n      \u003cdiv\u003e\u003csub\u003eLead Engineer \u0026 Open Source Enthusiast\u003c/sub\u003e\u003c/div\u003e\n      \u003cbr/\u003e\n      \u003cdiv\u003e\n        \u003ca href=\"https://github.com/shettayyy\" target=\"_blank\"\u003eGitHub\u003c/a\u003e ・\n        \u003ca href=\"https://twitter.com/shettayyy\" target=\"_blank\"\u003eTwitter\u003c/a\u003e ・\n        \u003ca href=\"https://linkedin.com/in/shettayyy\" target=\"_blank\"\u003eLinkedIn\u003c/a\u003e\n      \u003c/div\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Support\n\nIf you find class-glue useful, please consider:\n\n- Starring the [repository](https://github.com/shettayyy/class-glue) ⭐\n- [Supporting the project](https://github.com/sponsors/shettayyy) 💖\n- [Contributing](CONTRIBUTING.md) to the project 🤝\n- Sharing your feedback and ideas 💭\n- Referring to the project in your blog posts or articles 📝\n- Sharing the project with your friends and colleagues 👫\n\nThank you for your support! 🙏\n\n## Acknowledgements\n\nclass-glue is inspired by [clsx](https://github.com/lukeed/clsx), but with added features for TypeScript, CSS Modules, and React Native styles.\n\n## License\n\n[MIT](LICENSE) © [Rahul Shetty](https://github.com/shettayyy)\n\n---\n\n\u003cdiv align=\"center\"\u003e\n  \u003csub\u003eBuilt with ❤️ by Rahul Shetty and \u003ca href=\"https://github.com/shettayyy/class-glue/graphs/contributors\"\u003econtributors\u003c/a\u003e\u003c/sub\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshettayyy%2Fclass-glue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshettayyy%2Fclass-glue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshettayyy%2Fclass-glue/lists"}