Skip to content

Commit

Permalink
renamed to c
Browse files Browse the repository at this point in the history
  • Loading branch information
maphel committed Sep 4, 2023
1 parent 3213e3e commit 20465d7
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 225 deletions.
55 changes: 55 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"parser": "@typescript-eslint/parser",
"extends": [
"plugin:prettier/recommended",
"plugin:@typescript-eslint/recommended"
],
"plugins": [
"prettier"
],
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"env": {
"es2021": true,
"node": true
},
"rules": {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-comment": "off",
"no-console": "warn",
"no-throw-literal": "error",
"complexity": [
"warn",
20
],
"eqeqeq": [
"error",
"always"
],
"no-unused-vars": [
"off"
],
"no-var": "error",
"prefer-const": "error",
"prefer-arrow-callback": "error",
"semi": "off",
"quotes": [
"error",
"double"
]
},
"settings": {
"import/resolver": {
"node": {
"extensions": [
".js",
".jsx",
".ts",
".tsx"
]
}
}
}
}
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"singleQuote": false,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"printWidth": 120
}
15 changes: 8 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ Thank you for considering contributing to `@maphel/classnames`. We appreciate yo

1. **Fork the Repository**

Fork the `@maphel/classnames` repository on GitHub and clone your fork locally.
Fork the `@maphel/classes` repository on GitHub and clone your fork locally.

```sh
git clone https://github.com/[YOUR_USERNAME]/classnames.git
git clone https://github.com/maphel/classes.git
```

2. **Install Dependencies**

Navigate to the repository folder and install all necessary packages:

```sh
cd classnames
npm install
cd classes
yarn install
```

3. **Branching**
Expand All @@ -54,8 +54,9 @@ Thank you for considering contributing to `@maphel/classnames`. We appreciate yo
- Make sure your code lints and all tests pass. Run:

```sh
npm run lint
npm test
yarn lint
yarn test
yarn prettier
```

- Keep your code as clean and straightforward as possible.
Expand Down Expand Up @@ -97,5 +98,5 @@ Thank you for considering contributing to `@maphel/classnames`. We appreciate yo

## License

By contributing to `@maphel/classnames`, you agree that your contributions will be licensed under its MIT License.
By contributing to `@maphel/classes`, you agree that your contributions will be licensed under its MIT License.

47 changes: 27 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# `@maphel/classnames`
# `@maphel/classes`

![Classnames Package](https://img.shields.io/badge/@maphel-classnames-8A2BE2)
![NPM version](https://img.shields.io/npm/v/@maphel/classnames.svg)
![Build Status](https://img.shields.io/github/actions/workflow/status/maphel/classnames/build.yml)
![Coverage Status](https://img.shields.io/coverallsCoverage/github/maphel/classnames)
![License](https://img.shields.io/github/license/maphel/classnames)
![Classnames Package](https://img.shields.io/badge/@maphel-classes-8A2BE2)
![NPM version](https://img.shields.io/npm/v/@maphel/classes.svg)
![Build Status](https://img.shields.io/github/actions/workflow/status/maphel/classes/build.yml)
![Coverage Status](https://img.shields.io/coverallsCoverage/github/maphel/classes)
![License](https://img.shields.io/github/license/maphel/classes)


> The `@maphel/classnames` package is a TypeScript utility for easily managing CSS class names in your JavaScript or TypeScript application. Ideal for frontend frameworks like React, Angular, and Vue, it lets you dynamically generate className strings using conditions. Merge multiple class names, use conditionals, and manage UI state effortlessly.
> The `@maphel/classes` package is a TypeScript utility for easily managing CSS class names in your JavaScript or TypeScript application. Ideal for frontend frameworks like React, Angular, and Vue, it lets you dynamically generate className strings using conditions. Merge multiple class names, use conditionals, and manage UI state effortlessly.
---

Expand All @@ -28,27 +28,34 @@ Type Safety: Being written in TypeScript, it offers type safety while handling c
Conditional Classes: Easily apply class names based on conditions.
Array and Object Support: Accepts an array or object of class names, giving you flexibility in how you manage your classes.

## Why @maphel/classnames?
Working with dynamic class names often leads to cumbersome ternary or logical operations that can make the code less readable. The @maphel/classnames utility helps you create class name strings in a more expressive, readable, and error-free manner.
## Why @maphel/classes?
Working with dynamic class names often leads to cumbersome ternary or logical operations that can make the code less readable. The @maphel/classes utility helps you create class name strings in a more expressive, readable, and error-free manner.

---

## Installation
```bash
npm install @maphel/classnames
npm install @maphel/classes

yarn add @maphel/classes
```

## Usage
Import `classNames` into your TypeScript or JavaScript file.
Import `@maphel/classes` into your TypeScript or JavaScript file.
```typescript
import { cn } from '@maphel/classnames';
import { classNames } from '@maphel/classnames';
import { c } from '@maphel/classes';
import classes from '@maphel/classes';

var c = require('@maphel/classes').c;
var classes = require('@maphel/classes').default;
```

## API
```typescript
cn(...args: ClassValue[]): string;
classNames(...args: ClassValue[]): string;
type ClassProps = string | boolean | { [key: string]: string | boolean } | ClassProps[];

c(...args: ClassProps[]): string;
classes(...args: ClassProps[]): string;
```

### Parameters
Expand All @@ -62,22 +69,22 @@ Returns a concatenated string of class names based on `args`.

## Examples
```typescript
import { cn } from '@maphel/classnames';
import { c } from '@maphel/classes';

// Basic Usage
const basicResult = cn('class1', 'class2');
const basicResult = c('class1', 'class2');
console.log(basicResult); // Output: "class1 class2"

// Conditional Usage
const conditionalResult = cn('base', { 'active': true, 'disabled': false });
const conditionalResult = c('base', { 'active': true, 'disabled': false });
console.log(conditionalResult); // Output: "base active"

// Array Usage
const arrayResult = cn(['array-class1', 'array-class2']);
const arrayResult = c(['array-class1', 'array-class2']);
console.log(arrayResult); // Output: "array-class1 array-class2"

// Exessive Usage
const exessiveResult = cn('a', ['b', 'c'], {d: true}, ['e', {f: true}, ' g', 'h '], [' i ', [{' j': true}]], ' k', 'l ', ' m ');
const exessiveResult = c('a', ['b', 'c'], {d: true}, ['e', {f: true}, ' g', 'h '], [' i ', [{' j': true}]], ' k', 'l ', ' m ');
console.log(exessiveResult); // Output: "a b c d e f g h i j k l m"
```
---
Expand Down
19 changes: 14 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@maphel/classnames",
"name": "@maphel/classes",
"version": "0.0.1",
"description": "A utility for generating class names",
"main": "./dist/index.js",
Expand All @@ -8,23 +8,32 @@
"scripts": {
"test": "jest --coverage",
"build": "tsc",
"prepublish": "yarn build"
"prepublish": "yarn build",
"lint": "eslint src/**/*.{js,jsx,ts,tsx} --fix",
"prettier": "prettier --write \"src/**/*.ts\""
},
"devDependencies": {
"@types/jest": "^29.5.4",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"coveralls": "^3.1.1",
"eslint": "8.22.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.6.4",
"prettier": "^3.0.3",
"ts-jest": "^29.1.1",
"typescript": "^5.2.2"
},
"repository": {
"type": "git",
"url": "https://github.com/maphel/classnames.git"
"url": "https://github.com/maphel/classes.git"
},
"author": "",
"license": "MIT",
"bugs": {
"url": "https://github.com/maphel/classnames/issues"
"url": "https://github.com/maphel/classes/issues"
},
"homepage": "https://github.com/maphel/classnames#readme"
"homepage": "https://github.com/maphel/classes#readme",
"packageManager": "[email protected]"
}
136 changes: 136 additions & 0 deletions src/classes/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { c } from "./index"

describe("c", () => {
it("should return an empty string if no arguments are provided", () => {
expect(c()).toBe("")
})

it("should ignore undefined, null, and boolean arguments", () => {
expect(c(undefined, null, false, true)).toBe("")
})

it("should include string arguments", () => {
expect(c("class1", "class2")).toBe("class1 class2")
})

it("should filter out false keys in ClassMap and include true keys", () => {
expect(c({ class1: true, class2: false })).toBe("class1")
})

it("should filter out false keys in ClassMap and include true keys and add class3", () => {
expect(c({ class1: true, class2: false }, "class3")).toBe("class1 class3")
})

it("should filter out false keys in ClassMap and include true keys and add class3", () => {
expect(c({ class1: true, class2: false }, undefined, "class3")).toBe("class1 class3")
})

it("should handle a combination of all types of arguments", () => {
expect(
c(
"class1",
undefined,
null,
{
class2: true,
class3: false,
},
"class4",
),
).toBe("class1 class2 class4")
})

it('should ignore object arguments with non-boolean values except strings like "true" or "false" or "1" or "2"', () => {
expect(c({ class1: "true", class2: 123, class3: "1" } as any)).toBe("class1 class3")
})

it("should only include keys with boolean true values in mixed objects", () => {
expect(c({ class1: true, class2: "false", class3: 0 } as any)).toBe("class1")
})

it("should ignore empty strings", () => {
expect(c("class1", "", "class2")).toBe("class1 class2")
})

it("should include classes names with whitespace", () => {
expect(c("class1", "classes two")).toBe("class1 classes two")
})

it("should ignore number classes names", () => {
expect(c("class1", 123 as any, "class2")).toBe("class1 class2")
})

it("should ignore array inputs", () => {
expect(c("class1", ["class2", "class3"] as any)).toBe("class1 class2 class3")
})

it("should ignore nested objects", () => {
expect(c({ class1: true, nested: { class2: true } } as any)).toBe("class1")
})

it("should include classes names with leading or trailing whitespaces as-is", () => {
expect(c(" class1 ", "class2 ")).toBe("class1 class2")
})

it("should include classes names with array", () => {
expect(c(["class1", "class2"])).toBe("class1 class2")
})

it("should include classes names with array and string as 2nd parameter", () => {
expect(c(["class1", "class2"], "class3")).toBe("class1 class2 class3")
})

it("should include classes names with array with object and string additional parameter", () => {
expect(c(["class1", "class2"], "class3", { class4: true })).toBe("class1 class2 class3 class4")
})

it("should filter out false keys in ClassMap and include true keys", () => {
expect(c({ class1: true, class2: false })).toBe("class1")
})

it("evaluate all features", () => {
expect(
c("a", ["b", "c"], { d: true }, ["e", { f: true }, " g", "h "], [" i ", [{ " j": true }]], " k", "l ", " m "),
).toBe("a b c d e f g h i j k l m")
})

it("should return empty string for no arguments", () => {
expect(c()).toBe("")
})

it("should concatenate classes names", () => {
expect(c("a", "b")).toBe("a b")
})

it("should omit falsy values", () => {
expect(c("a", null, false, "b")).toBe("a b")
})

it("should include truthy values from an object", () => {
expect(c("a", { b: true, c: false }, "d")).toBe("a b d")
})

it("should work with arrays", () => {
expect(c(["a", "b"])).toBe("a b")
})

it("should work with nested arrays", () => {
expect(c(["a", ["b", "c"]])).toBe("a b c")
})

it("should work with arrays containing objects", () => {
expect(c(["a", { b: true }])).toBe("a b")
})

it("should work with deeply nested structures", () => {
expect(c(["a", ["b", { c: true }], [["d", { e: true }]]])).toBe("a b c d e")
})

it("should work with only one object", () => {
expect(c({ e: true })).toBe("e")
})

it("should work with only one string", () => {
expect(c("e")).toBe("e")
})
})
Loading

0 comments on commit 20465d7

Please sign in to comment.