classname-variants 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,8 @@ Library to create type-safe components that render their class name based on a s
7
7
  - ⚛️ Supports React, Preact and vanilla DOM
8
8
  - 🛡️ Fully type-safe and excellent auto completion support
9
9
  - ✅ Supports both optional and required variants
10
- - 🪶 Light-weight without any dependencies
10
+ - 🔗 Supports custom strategies like [tailwind-merge](https://www.npmjs.com/package/tailwind-merge)
11
+ - 🪶 [Light-weight](https://bundlephobia.com/package/classname-variants) without any dependencies
11
12
 
12
13
  ![npm bundle size](https://img.shields.io/bundlephobia/minzip/classname-variants)
13
14
 
@@ -232,6 +233,23 @@ The component can then be rendered as button or as anchor or even as custom comp
232
233
  </>
233
234
  ```
234
235
 
236
+ ### Using a custom strategy to combine class names
237
+
238
+ The built-in strategy for combining multiple class names into one string is simple and straightforward:
239
+
240
+ ```ts
241
+ (classes) => classes.filter(Boolean).join(" ");
242
+ ```
243
+
244
+ If you [want](https://github.com/dcastil/tailwind-merge/blob/main/docs/when-and-how-to-use-it.md), you can use a custom strategy like tailwind-merge instead:
245
+
246
+ ```ts
247
+ import { classNames } from "classname-variants";
248
+ import { twMerge } from "tailwind-merge";
249
+
250
+ classNames.combine = twMerge;
251
+ ```
252
+
235
253
  # Tailwind IntelliSense
236
254
 
237
255
  In order to get auto-completion for the CSS classes themselves, you can use the [Tailwind CSS IntelliSense](https://github.com/tailwindlabs/tailwindcss-intellisense) plugin for VS Code. In order to make it recognize the strings inside your variants-config, you have to somehow mark them and configure the plugin accordingly.
package/lib/index.d.ts CHANGED
@@ -101,6 +101,9 @@ export type VariantOptions<C extends VariantsConfig<V>, V extends Variants = C["
101
101
  export type Simplify<T> = {
102
102
  [K in keyof T]: T[K];
103
103
  };
104
+ export declare const classNames: {
105
+ combine: (...classes: Array<string | undefined | null | false | 0>) => string;
106
+ };
104
107
  export declare function variants<C extends VariantsConfig<V>, V extends Variants = C["variants"]>(config: Simplify<C>): (props: VariantOptions<C>) => string;
105
108
  /**
106
109
  * No-op function to mark template literals as tailwind strings.
package/lib/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ export const classNames = {
2
+ combine: (...classes) => classes.filter(Boolean).join(" "),
3
+ };
1
4
  export function variants(config) {
2
5
  const { base, variants, compoundVariants, defaultVariants } = config;
3
6
  const isBooleanVariant = (name) => {
@@ -6,7 +9,7 @@ export function variants(config) {
6
9
  };
7
10
  return (props) => {
8
11
  var _a;
9
- const res = [base];
12
+ const classes = base ? [base] : [];
10
13
  const getSelected = (name) => {
11
14
  var _a, _b;
12
15
  return (_b = (_a = props[name]) !== null && _a !== void 0 ? _a : defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[name]) !== null && _b !== void 0 ? _b : (isBooleanVariant(name) ? false : undefined);
@@ -14,15 +17,15 @@ export function variants(config) {
14
17
  for (let name in variants) {
15
18
  const selected = getSelected(name);
16
19
  if (selected !== undefined)
17
- res.push((_a = variants[name]) === null || _a === void 0 ? void 0 : _a[selected]);
20
+ classes.push((_a = variants[name]) === null || _a === void 0 ? void 0 : _a[selected]);
18
21
  }
19
22
  for (let { variants, className } of compoundVariants !== null && compoundVariants !== void 0 ? compoundVariants : []) {
20
23
  const isSelected = (name) => getSelected(name) === variants[name];
21
24
  if (Object.keys(variants).every(isSelected)) {
22
- res.push(className);
25
+ classes.push(className);
23
26
  }
24
27
  }
25
- return res.filter(Boolean).join(" ");
28
+ return classNames.combine(...classes);
26
29
  };
27
30
  }
28
31
  /**
package/lib/preact.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { h } from "preact";
2
2
  import { forwardRef } from "preact/compat";
3
- import { variants, } from "./index.js";
3
+ import { variants, classNames, } from "./index.js";
4
4
  export function variantProps(config) {
5
5
  const variantClassName = variants(config);
6
6
  return (props) => {
@@ -12,9 +12,7 @@ export function variantProps(config) {
12
12
  }
13
13
  }
14
14
  // Add the optionally passed class/className prop for chaining
15
- result.class = [variantClassName(props), props.class, props.className]
16
- .filter(Boolean)
17
- .join(" ");
15
+ result.class = classNames.combine(variantClassName(props), props.class, props.className);
18
16
  return result;
19
17
  };
20
18
  }
package/lib/react.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createElement, forwardRef, } from "react";
2
- import { variants, } from "./index.js";
2
+ import { variants, classNames, } from "./index.js";
3
3
  export function variantProps(config) {
4
4
  const variantClassName = variants(config);
5
5
  return (props) => {
@@ -11,9 +11,7 @@ export function variantProps(config) {
11
11
  }
12
12
  }
13
13
  // Add the optionally passed className prop for chaining
14
- result.className = [variantClassName(props), props.className]
15
- .filter(Boolean)
16
- .join(" ");
14
+ result.className = classNames.combine(variantClassName(props), props.className);
17
15
  return result;
18
16
  };
19
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "classname-variants",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Variant API for plain class names",
5
5
  "author": "Felix Gnass <fgnass@gmail.com>",
6
6
  "license": "MIT",