Comparing version 2.0.0-0 to 2.0.0-1
{ | ||
"editor.formatOnSave": true, | ||
"testing.automaticallyOpenPeekView": "never", | ||
"typescript.tsdk": "node_modules/typescript/lib" | ||
"typescript.tsdk": "node_modules/typescript/lib", | ||
"tailwindCSS.experimental.classRegex": [ | ||
["onno\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"] | ||
] | ||
} |
@@ -7,4 +7,12 @@ ### Changelog | ||
#### [2.0.0-1](https://github.com/wagerfield/onno/compare/2.0.0-0...2.0.0-1) | ||
- docs: add config documentation [`fa15487`](https://github.com/wagerfield/onno/commit/fa154874cf60d81febdca83ebaa344572d422f8f) | ||
- docs: add class composition section [`2f3cdc0`](https://github.com/wagerfield/onno/commit/2f3cdc0895c6ff9b2384239e0a7ad34f0d82cd34) | ||
- docs: write compound classes section [`589425e`](https://github.com/wagerfield/onno/commit/589425effd73b6a4697c11166ec98bd083ae3eef) | ||
#### [2.0.0-0](https://github.com/wagerfield/onno/compare/1.0.0...2.0.0-0) | ||
> 7 August 2023 | ||
- ci: add npm publish workflow [`#469`](https://github.com/wagerfield/onno/pull/469) | ||
@@ -11,0 +19,0 @@ - feat: setup codecov [`#466`](https://github.com/wagerfield/onno/pull/466) |
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "2.0.0-0", | ||
"version": "2.0.0-1", | ||
"main": "dist/index.cjs", | ||
@@ -8,0 +8,0 @@ "module": "dist/index.mjs", |
257
readme.md
# [![onno](https://raw.github.com/wagerfield/onno/main/assets/onno.svg)][onno] | ||
[![Bundle Size](https://img.shields.io/bundlephobia/minzip/onno?style=flat-square&logo=npm&logoColor=FFF&label=size&color=4C8)][bundlephobia-onno] | ||
[![Code Coverage](https://img.shields.io/codecov/c/gh/wagerfield/onno?style=flat-square&logo=codecov&logoColor=FFF&color=4C8)][codecov] | ||
[![Workflow Status](https://img.shields.io/github/actions/workflow/status/wagerfield/onno/test.yml?style=flat-square&logo=github&logoColor=FFF&color=4C8)][workflow] | ||
[![License](https://img.shields.io/github/license/wagerfield/onno?style=flat-square&color=4C8)][license] | ||
[![Bundle Size](https://img.shields.io/bundlephobia/minzip/onno?style=flat-square&logo=npm&logoColor=FFF&label=size&color=4C8)][onno-bundlephobia] | ||
[![Code Coverage](https://img.shields.io/codecov/c/gh/wagerfield/onno?style=flat-square&logo=codecov&logoColor=FFF&color=4C8)][onno-codecov] | ||
[![Workflow Status](https://img.shields.io/github/actions/workflow/status/wagerfield/onno/test.yml?style=flat-square&logo=github&logoColor=FFF&color=4C8)][onno-workflow] | ||
[![License](https://img.shields.io/github/license/wagerfield/onno?style=flat-square&color=4C8)][onno-license] | ||
Tiny ([510B][bundlephobia-onno]) utility for composing class variants using `clsx` | ||
Tiny ([596B][onno-bundlephobia]) utility for composing class variants using `clsx` | ||
@@ -14,7 +14,7 @@ pnpm add onno | ||
- Framework agnostic | ||
- Single _tiny_ dependency on `clsx` ([330B][bundlephobia-clsx]) | ||
- Written in [TypeScript][typescript] with lovely [type helpers](#typescript) | ||
- Rigorously tested with [100% code coverage][codecov] | ||
- Perfect companion to [Tailwind CSS][tailwindcss] | ||
- :rocket: Framework agnostic | ||
- :mouse: Single _tiny_ dependency on `clsx` ([330B][clsx-bundlephobia]) | ||
- :yum: Written in [TypeScript][typescript] with delicious [type helpers](#typescript) | ||
- :test_tube: Rigorously tested with [100% code coverage][onno-codecov] | ||
- :handshake: Perfect companion to [Tailwind CSS][tailwindcss] | ||
@@ -26,6 +26,2 @@ ## Usage | ||
variants: { | ||
intent: { | ||
primary: "bg-blue-600 text-white", | ||
secondary: "bg-gray-200 text-black", | ||
}, | ||
size: { | ||
@@ -36,10 +32,12 @@ sm: "h-8 px-1", | ||
}, | ||
intent: { | ||
primary: "bg-blue-600 text-white", | ||
secondary: "bg-gray-200 text-black", | ||
}, | ||
disabled: "opacity-50", | ||
}, | ||
}) | ||
// "bg-blue-600 text-white h-10 px-2" | ||
const classes = button({ | ||
intent: "primary", | ||
size: "md", | ||
}) | ||
// "h-10 px-2 bg-blue-600 text-white opacity-50" | ||
const classes = button({ size: "md", intent: "primary", disabled: true }) | ||
``` | ||
@@ -49,23 +47,192 @@ | ||
Todo | ||
Define variant names and the classes to be applied to them using the `variants` config option: | ||
```js | ||
// Name your function whatever you like! | ||
const button = onno({ | ||
variants: { | ||
// This is a `boolean` variant applied when `disabled === true` | ||
disabled: "access denied", // Classes can be defined as a `string` | ||
// This is another `boolean` variant applied when `hidden === true` | ||
hidden: ["barely", "visible"], // Classes can also be a `string[]` | ||
// This is a `enum` variant applied when `size === "sm" || "lg"` | ||
size: { | ||
sm: ["pretty", "small"], // Here we are using a `string[]` class list | ||
lg: "really large", // ...and here we are using a `string` class list | ||
}, | ||
}, | ||
}) | ||
button() // "" | ||
button({}) // "" | ||
button({ size: "sm" }) // "pretty small" | ||
button({ disabled: true }) // "access denied" | ||
button({ hidden: true, size: "lg" }) // "barely visible really large" | ||
``` | ||
Note that you cannot use `className` as a variant key since it is _reserved_ for applying [additional classes](#additional-classes): | ||
```js | ||
const button = onno({ | ||
variants: { | ||
className: "not allowed", // Error: "className" cannot be used as a variant name | ||
}, | ||
}) | ||
``` | ||
### Defaults | ||
Todo | ||
Default variants can be set using the `defaults` config option: | ||
```js | ||
const button = onno({ | ||
defaults: { | ||
hidden: true, | ||
intent: "secondary", | ||
}, | ||
variants: { | ||
hidden: "barely visible", | ||
intent: { | ||
primary: "super punchy", | ||
secondary: "quite bland", | ||
}, | ||
size: { | ||
sm: "pretty small", | ||
lg: "really large", | ||
}, | ||
}, | ||
}) | ||
button() // "barely visible quite bland" | ||
button({}) // "barely visible quite bland" | ||
button({ hidden: false }) // "quite bland" | ||
button({ intent: "primary" }) // "barely visible super punchy" | ||
button({ size: "sm" }) // "barely visible quite bland pretty small" | ||
``` | ||
### Baseline Classes | ||
Todo | ||
Common classes can be applied using the `baseline` config option: | ||
```js | ||
const button = onno({ | ||
baseline: "solid base", // Can also use a `string[]` class list | ||
variants: { | ||
size: { | ||
sm: "pretty small", | ||
lg: "really large", | ||
}, | ||
}, | ||
}) | ||
button() // "solid base" | ||
button({}) // "solid base" | ||
button({ size: "lg" }) // "solid base really large" | ||
``` | ||
### Compound Classes | ||
Todo | ||
Apply classes when certain variants are combined using the `compound` config option: | ||
```js | ||
const button = onno({ | ||
variants: { | ||
hidden: "barely visible", | ||
size: { | ||
sm: "pretty small", | ||
md: "kinda normal", | ||
lg: "really large", | ||
}, | ||
}, | ||
compound: [ | ||
{ | ||
size: ["sm", "lg"], | ||
className: ["compound", "one"], // Applied when `size === "sm" || "lg"` | ||
}, | ||
{ | ||
size: "md", | ||
hidden: true, | ||
className: "compound two", // Applied when `size === "md" && hidden === true` | ||
}, | ||
], | ||
}) | ||
button() // "" | ||
button({}) // "" | ||
button({ size: "md" }) // "kinda normal" | ||
button({ hidden: true }) // "barely visible" | ||
button({ size: "lg" }) // "really large compound one" | ||
button({ size: "md", hidden: true }) // "barely visible kinda normal compound two" | ||
``` | ||
### Additional Classes | ||
Todo | ||
Additional classes can be applied using the `className` option: | ||
```js | ||
const button = onno({ | ||
baseline: "solid base", | ||
variants: { | ||
size: { | ||
sm: "pretty small", | ||
lg: "really large", | ||
}, | ||
}, | ||
}) | ||
button() // "solid base" | ||
button({ className: "with more" }) // "solid base with more" | ||
button({ className: "with more", size: "sm" }) // "solid base pretty small with more" | ||
``` | ||
### Class Composition | ||
Classes are applied in the following order: | ||
1. `baseline` | ||
2. `variants` | ||
3. `compound` | ||
4. `className` | ||
Under the hood `onno` uses `clsx` to build the class list ([see `clsx` docs][clsx]). | ||
For convenience `clsx` is exported from `onno` so you can use it to compose classes: | ||
```js | ||
import { onno, clsx } from "onno" | ||
const button = onno({ | ||
variants: { | ||
size: { | ||
sm: "pretty small", | ||
lg: "really large", | ||
}, | ||
}, | ||
}) | ||
clsx("foo", ["bar", { baz: true }], button({ size: "sm" })) // "foo bar baz pretty small" | ||
``` | ||
Note that onno's `className` option also accepts any `clsx.ClassValue` so you can do: | ||
```js | ||
import { onno, clsx } from "onno" | ||
const button = onno({ | ||
variants: { | ||
size: { | ||
sm: "pretty small", | ||
lg: "really large", | ||
}, | ||
}, | ||
}) | ||
button({ size: "lg", className: ["foo", ["bar"], { baz: true }] }) // "really large foo bar baz" | ||
``` | ||
## TypeScript | ||
Use `OnnoProps` to infer variant props from an `OnnoFunction` | ||
Use the `OnnoProps` type to infer variant props from an `OnnoFunction` | ||
@@ -77,2 +244,3 @@ ```ts | ||
variants: { | ||
disabled: "not allowed", | ||
size: { | ||
@@ -87,5 +255,6 @@ sm: "pretty small", | ||
export type ButtonSizeType = ButtonProps["size"] // "sm" | "lg" | undefined | ||
export type ButtonDisabledType = ButtonProps["disabled"] // boolean | undefined | ||
``` | ||
Note that inferred `OnnoProps` include the `className` option alongside the variant types: | ||
Note that the inferred `OnnoProps` also includes the `className` option alongside the variant types: | ||
@@ -96,3 +265,3 @@ ```ts | ||
By default all variants are _optional_. To require one or more variants, pass a union of _required_ variant keys as the second argument to the `OnnoProps` type: | ||
By default all variants inferred by `OnnoProps` are _optional_. To require one or more variants, pass a union of _required_ variant keys as the second argument to the `OnnoProps` generic type: | ||
@@ -106,4 +275,4 @@ ```ts | ||
intent: { | ||
primary: "very punchy", | ||
secondary: "quite normal", | ||
primary: "super punchy", | ||
secondary: "quite bland", | ||
}, | ||
@@ -123,14 +292,30 @@ size: { | ||
## Tailwind CSS | ||
If you are using the [Tailwind CSS VSCode extension][tailwindcss-vscode] add the following configuration to your workspace `.vscode/settings.json` file: | ||
```json | ||
{ | ||
"tailwindCSS.experimental.classRegex": [ | ||
["onno\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"] | ||
] | ||
} | ||
``` | ||
This will trigger Tailwind's class name autocompletion within the `onno()` function call. | ||
## License | ||
[MIT][license] © [Matthew Wagerfield][wagerfield] | ||
[MIT][onno-license] © [Matthew Wagerfield][wagerfield] | ||
[onno]: https://onnojs.com | ||
[wagerfield]: https://github.com/wagerfield | ||
[codecov]: https://codecov.io/gh/wagerfield/onno | ||
[license]: https://github.com/wagerfield/onno/blob/main/license | ||
[workflow]: https://github.com/wagerfield/onno/actions/workflows/test.yml | ||
[bundlephobia-clsx]: https://bundlephobia.com/package/clsx@2.0.0 | ||
[bundlephobia-onno]: https://bundlephobia.com/package/onno@2.0.0 | ||
[onno]: https://github.com/wagerfield/onno#readme | ||
[onno-workflow]: https://github.com/wagerfield/onno/actions/workflows/test.yml | ||
[onno-license]: https://github.com/wagerfield/onno/blob/main/license | ||
[onno-codecov]: https://codecov.io/gh/wagerfield/onno | ||
[clsx-bundlephobia]: https://bundlephobia.com/package/clsx | ||
[onno-bundlephobia]: https://bundlephobia.com/package/onno | ||
[clsx]: https://github.com/lukeed/clsx#readme | ||
[typescript]: https://www.typescriptlang.org | ||
[tailwindcss]: https://tailwindcss.com | ||
[tailwindcss-vscode]: https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss |
@@ -49,2 +49,5 @@ import { describe, expect, it } from "vitest" | ||
expect(fn({ className: ["with", "className"] })).toBe("base with className") | ||
expect(fn({ className: ["foo", ["bar"], { baz: true }] })).toBe( | ||
"base foo bar baz", | ||
) | ||
}) | ||
@@ -51,0 +54,0 @@ |
import { ClassValue } from "clsx" | ||
// Class Types | ||
export type { ClassValue } | ||
@@ -9,2 +11,6 @@ | ||
// Utility Types | ||
export type Flatten<T> = T extends object ? {} & { [P in keyof T]: T[P] } : T | ||
// Onno Class Types | ||
@@ -34,4 +40,4 @@ | ||
baseline?: OnnoClassValue | ||
compound?: OnnoCompound<T>[] | ||
defaults?: OnnoDefaults<T> | ||
compound?: Flatten<OnnoCompound<T>>[] | ||
defaults?: Flatten<OnnoDefaults<T>> | ||
variants: T | ||
@@ -45,3 +51,3 @@ } | ||
export type OnnoFunction<T extends OnnoVariants> = ( | ||
options?: OnnoOptions<T>, | ||
options?: Flatten<OnnoOptions<T>>, | ||
) => string | ||
@@ -55,3 +61,3 @@ | ||
type OnnoVariantProps<F extends OnnoFunction<any>> = Omit< | ||
export type OnnoVariantProps<F extends OnnoFunction<any>> = Omit< | ||
Exclude<Parameters<F>[0], undefined>, | ||
@@ -64,2 +70,4 @@ ClassKey | ||
K extends keyof OnnoVariantProps<F> = never, | ||
> = OnnoVariantProps<F> & Required<Pick<OnnoVariantProps<F>, K>> & ClassProps | ||
> = Flatten< | ||
OnnoVariantProps<F> & Required<Pick<OnnoVariantProps<F>, K>> & ClassProps | ||
> |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
217183
28
359
313
0