Cn utility refactor (#2915)

* refactor(core): cn utility adjusted and moved to the theme package

* chore(root): changeset

* fix(storybook): stories that used cn
This commit is contained in:
Junior Garcia 2024-04-29 17:34:01 -03:00 committed by GitHub
parent f8b917a208
commit e3afa4789a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 80 additions and 33 deletions

View File

@ -0,0 +1,7 @@
---
"@nextui-org/system": patch
"@nextui-org/system-rsc": patch
"@nextui-org/theme": patch
---
The `cn` utility was moved the `theme` package and updated to support NextUI custom classes.

View File

@ -12,7 +12,7 @@ import {
import {I18nProvider, useLocale} from "@react-aria/i18n";
import {Button, ButtonGroup} from "@nextui-org/button";
import {Radio, RadioGroup} from "@nextui-org/radio";
import {cn} from "@nextui-org/system";
import {cn} from "@nextui-org/theme";
import {Calendar, CalendarProps, DateValue} from "../src";

View File

@ -16,7 +16,7 @@ import {
import {I18nProvider, useLocale} from "@react-aria/i18n";
import {Button, ButtonGroup} from "@nextui-org/button";
import {Radio, RadioGroup} from "@nextui-org/radio";
import {cn} from "@nextui-org/system";
import {cn} from "@nextui-org/theme";
import {RangeCalendar, RangeCalendarProps} from "../src";

View File

@ -16,7 +16,7 @@ import {
import {I18nProvider, useDateFormatter, useLocale} from "@react-aria/i18n";
import {Button, ButtonGroup} from "@nextui-org/button";
import {Radio, RadioGroup} from "@nextui-org/radio";
import {cn} from "@nextui-org/system";
import {cn} from "@nextui-org/theme";
import {DatePicker, DatePickerProps} from "../src";

View File

@ -18,7 +18,7 @@ import {DateValue} from "@react-types/datepicker";
import {I18nProvider, useDateFormatter, useLocale} from "@react-aria/i18n";
import {Button, ButtonGroup} from "@nextui-org/button";
import {Radio, RadioGroup} from "@nextui-org/radio";
import {cn} from "@nextui-org/system";
import {cn} from "@nextui-org/theme";
import {DateRangePicker, DateRangePickerProps} from "../src";

View File

@ -1,7 +1,7 @@
import React from "react";
import {Meta} from "@storybook/react";
import {button, pagination} from "@nextui-org/theme";
import {cn} from "@nextui-org/system";
import {cn} from "@nextui-org/theme";
import {ChevronIcon} from "@nextui-org/shared-icons";
import {Pagination, PaginationItemRenderProps, PaginationItemType, usePagination} from "../src";

View File

@ -4,7 +4,7 @@ import {Meta} from "@storybook/react";
import {slider} from "@nextui-org/theme";
import {InfoIcon, VolumeHighBoldIcon, VolumeLowBoldIcon} from "@nextui-org/shared-icons";
import {Tooltip} from "@nextui-org/tooltip";
import {cn} from "@nextui-org/system";
import {cn} from "@nextui-org/theme";
import {Slider, SliderProps, SliderValue} from "../src";

View File

@ -35,8 +35,7 @@
},
"peerDependencies": {
"react": ">=18",
"@nextui-org/theme": ">=2.1.0",
"tailwind-variants": ">=0.1.13"
"@nextui-org/theme": ">=2.1.0"
},
"devDependencies": {
"react": "^18.0.0",

View File

@ -1,7 +1,8 @@
import * as React from "react";
import {tv} from "@nextui-org/theme";
import clsx from "clsx";
import {cn, mapPropsVariants} from "./utils";
import {mapPropsVariants} from "./utils";
function getSlots(variants) {
return variants
@ -65,7 +66,7 @@ function getClassNamesWithProps({
// if no slots, the result is a string
if (!hasSlots) {
newProps.className = cn(result, props.className);
newProps.className = clsx(result, props.className);
}
// if has slots, the result is an object with keys as slots functions
else {
@ -78,7 +79,7 @@ function getClassNamesWithProps({
});
Object.entries(props.classNames ?? {}).forEach(([key, value]) => {
classNames[key] = cn(classNames[key], value);
classNames[key] = clsx(classNames[key], value);
});
}

View File

@ -15,7 +15,6 @@ export type {
} from "./types";
export {
cn,
forwardRef,
toIterator,
mapPropsVariants,

View File

@ -1,7 +1,6 @@
import type {As, RightJoinProps, PropsOf, InternalForwardRefRenderFunction} from "./types";
import * as React from "react";
import clsx from "clsx";
import {forwardRef as baseForwardRef} from "react";
export function forwardRef<
@ -96,11 +95,6 @@ export const mapPropsVariantsWithCommon = <
return [props, variants] as const;
};
/**
* Classnames utility
*/
export const cn = clsx;
/**
* Checks if a component is a NextUI component.
* @param component - The component to check.

View File

@ -4,8 +4,9 @@ import React, {useMemo} from "react";
import {SlotsToClasses, tv, type VariantProps} from "@nextui-org/theme";
import {filterDOMProps, ReactRef, useDOMRef} from "@nextui-org/react-utils";
import {objectToDeps} from "@nextui-org/shared-utils";
import clsx from "clsx";
import {cn, forwardRef, mapPropsVariants} from "../src/utils";
import {forwardRef, mapPropsVariants} from "../src/utils";
const card = tv({
slots: {
@ -171,7 +172,7 @@ export const Card = forwardRef<"div", CardProps>((originalProps, ref) => {
const styles = useMemo(() => card({...variantProps}), [objectToDeps(variantProps)]);
const baseStyles = cn(classNames?.base, className);
const baseStyles = clsx(classNames?.base, className);
const domRef = useDOMRef(ref);

View File

@ -18,7 +18,6 @@ export type {
} from "@nextui-org/system-rsc";
export {
cn,
forwardRef,
toIterator,
mapPropsVariants,

View File

@ -55,7 +55,9 @@
"lodash.kebabcase": "^4.1.1",
"lodash.mapkeys": "^4.6.0",
"lodash.omit": "^4.5.0",
"tailwind-variants": "^0.1.20"
"clsx": "^1.2.1",
"tailwind-variants": "^0.1.20",
"tailwind-merge": "^1.14.0"
},
"peerDependencies": {
"tailwindcss": ">=3.4.0"

View File

@ -0,0 +1,17 @@
import type {ClassValue} from "clsx";
import clsx from "clsx";
import {extendTailwindMerge} from "tailwind-merge";
import {twMergeConfig} from "./tw-merge-config";
/**
* We need to extend the tailwind merge to include NextUI's custom classes.
*
* So we can use classes like `text-small` or `text-default-500` and override them.
*/
const twMerge = extendTailwindMerge(twMergeConfig);
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}

View File

@ -1,3 +1,14 @@
export * from "./classes";
export * from "./types";
export * from "./variants";
export {
baseStyles,
ringClasses,
focusVisibleClasses,
dataFocusVisibleClasses,
groupDataFocusVisibleClasses,
translateCenterClasses,
absoluteFullClasses,
collapseAdjacentVariantBorders,
} from "./classes";
export type {SlotsToClasses} from "./types";
export {colorVariants} from "./variants";
export {COMMON_UNITS, twMergeConfig} from "./tw-merge-config";
export {cn} from "./cn";

View File

@ -1,6 +1,6 @@
import {tv as tvBase, TV} from "tailwind-variants";
const COMMON_UNITS = ["small", "medium", "large"];
import {twMergeConfig} from "./tw-merge-config";
export const tv: TV = (options, config) =>
tvBase(options, {
@ -10,16 +10,11 @@ export const tv: TV = (options, config) =>
...config?.twMergeConfig,
theme: {
...config?.twMergeConfig?.theme,
opacity: ["disabled"],
spacing: ["divider"],
borderWidth: COMMON_UNITS,
borderRadius: COMMON_UNITS,
...twMergeConfig.theme,
},
classGroups: {
...config?.twMergeConfig?.classGroups,
shadow: [{shadow: COMMON_UNITS}],
"font-size": [{text: ["tiny", ...COMMON_UNITS]}],
"bg-image": ["bg-stripe-gradient"],
...twMergeConfig.classGroups,
},
},
});

View File

@ -0,0 +1,16 @@
import type {Config} from "tailwind-merge";
export const COMMON_UNITS = ["small", "medium", "large"];
export const twMergeConfig: Partial<Config> = {
theme: {
opacity: ["disabled"],
spacing: ["divider"],
borderWidth: COMMON_UNITS,
borderRadius: COMMON_UNITS,
},
classGroups: {
shadow: [{shadow: COMMON_UNITS}],
"font-size": [{text: ["tiny", ...COMMON_UNITS]}],
"bg-image": ["bg-stripe-gradient"],
},
};

6
pnpm-lock.yaml generated
View File

@ -3020,6 +3020,9 @@ importers:
packages/core/theme:
dependencies:
clsx:
specifier: ^1.2.1
version: 1.2.1
color:
specifier: ^4.2.3
version: 4.2.3
@ -3047,6 +3050,9 @@ importers:
lodash.omit:
specifier: ^4.5.0
version: 4.5.0
tailwind-merge:
specifier: ^1.14.0
version: 1.14.0
tailwind-variants:
specifier: ^0.1.20
version: 0.1.20(tailwindcss@3.4.3)