Skip to content

Commit

Permalink
fix: compound slots with variants (#118)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrgarciadev authored Oct 24, 2023
1 parent 72272e9 commit a97aa84
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 7 deletions.
206 changes: 205 additions & 1 deletion src/__tests__/tv.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -789,12 +789,216 @@ describe("Tailwind Variants (TV) - Slots", () => {

const {base, cursor} = menu();

expect(base()).toEqual("flex flex-wrap w-7 h-7 text-xs");
expect(base()).toEqual("flex flex-wrap");
expect(base({size: "xs"})).toEqual("flex flex-wrap w-7 h-7 text-xs");
expect(base({size: "sm"})).toEqual("flex flex-wrap w-7 h-7 text-xs");
expect(cursor()).toEqual("absolute flex overflow-visible");
});

test("should not override the default classes when the variant doesn't match - compoundSlots", () => {
const tabs = tv({
slots: {
base: "inline-flex",
tabList: ["flex"],
tab: ["z-0", "w-full", "px-3", "py-1", "flex", "group", "relative"],
tabContent: ["relative", "z-10", "text-inherit", "whitespace-nowrap"],
cursor: ["absolute", "z-0", "bg-white"],
panel: ["py-3", "px-1", "outline-none"],
},
variants: {
variant: {
solid: {},
light: {},
underlined: {},
bordered: {},
},
color: {
default: {},
primary: {},
secondary: {},
success: {},
warning: {},
danger: {},
},
size: {
sm: {
tabList: "rounded-md",
tab: "h-7 text-xs rounded-sm",
cursor: "rounded-sm",
},
md: {
tabList: "rounded-md",
tab: "h-8 text-sm rounded-sm",
cursor: "rounded-sm",
},
lg: {
tabList: "rounded-lg",
tab: "h-9 text-md rounded-md",
cursor: "rounded-md",
},
},
radius: {
none: {
tabList: "rounded-none",
tab: "rounded-none",
cursor: "rounded-none",
},
sm: {
tabList: "rounded-md",
tab: "rounded-sm",
cursor: "rounded-sm",
},
md: {
tabList: "rounded-md",
tab: "rounded-sm",
cursor: "rounded-sm",
},
lg: {
tabList: "rounded-lg",
tab: "rounded-md",
cursor: "rounded-md",
},
full: {
tabList: "rounded-full",
tab: "rounded-full",
cursor: "rounded-full",
},
},
},
defaultVariants: {
color: "default",
variant: "solid",
size: "md",
},
compoundSlots: [
{
variant: "underlined",
slots: ["tab", "tabList", "cursor"],
class: ["rounded-none"],
},
],
});

const {tab, tabList, cursor} = tabs();

expectTv(tab(), [
"z-0",
"w-full",
"px-3",
"py-1",
"h-8",
"flex",
"group",
"relative",
"text-sm",
"rounded-sm",
]);
expectTv(tabList(), ["flex", "rounded-md"]);
expectTv(cursor(), ["absolute", "z-0", "bg-white", "rounded-sm"]);
});

test("should override the default classes when the variant matches - compoundSlots", () => {
const tabs = tv({
slots: {
base: "inline-flex",
tabList: ["flex"],
tab: ["z-0", "w-full", "px-3", "py-1", "flex", "group", "relative"],
tabContent: ["relative", "z-10", "text-inherit", "whitespace-nowrap"],
cursor: ["absolute", "z-0", "bg-white"],
panel: ["py-3", "px-1", "outline-none"],
},
variants: {
variant: {
solid: {},
light: {},
underlined: {},
bordered: {},
},
color: {
default: {},
primary: {},
secondary: {},
success: {},
warning: {},
danger: {},
},
size: {
sm: {
tabList: "rounded-md",
tab: "h-7 text-xs rounded-sm",
cursor: "rounded-sm",
},
md: {
tabList: "rounded-md",
tab: "h-8 text-sm rounded-sm",
cursor: "rounded-sm",
},
lg: {
tabList: "rounded-lg",
tab: "h-9 text-md rounded-md",
cursor: "rounded-md",
},
},
radius: {
none: {
tabList: "rounded-none",
tab: "rounded-none",
cursor: "rounded-none",
},
sm: {
tabList: "rounded-md",
tab: "rounded-sm",
cursor: "rounded-sm",
},
md: {
tabList: "rounded-md",
tab: "rounded-sm",
cursor: "rounded-sm",
},
lg: {
tabList: "rounded-lg",
tab: "rounded-md",
cursor: "rounded-md",
},
full: {
tabList: "rounded-full",
tab: "rounded-full",
cursor: "rounded-full",
},
},
},
defaultVariants: {
color: "default",
variant: "solid",
size: "md",
},
compoundSlots: [
{
variant: "underlined",
slots: ["tab", "tabList", "cursor"],
class: ["rounded-none"],
},
],
});

const {tab, tabList, cursor} = tabs({variant: "underlined"});

expectTv(tab(), [
"z-0",
"w-full",
"px-3",
"py-1",
"h-8",
"flex",
"group",
"relative",
"text-sm",
"rounded-none",
]);
expectTv(tabList(), ["flex", "rounded-none"]);
expectTv(cursor(), ["absolute", "z-0", "bg-white", "rounded-none"]);
});

test("should support slot level variant overrides - compoundVariants", () => {
const menu = tv({
base: "text-3xl",
Expand Down
22 changes: 16 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
removeExtraSpaces,
flatMergeArrays,
flatArray,
isBoolean,
} from "./utils.js";

export const defaultConfig = {
Expand Down Expand Up @@ -347,18 +348,22 @@ export const tv = (options, configProp) => {
className: slotClassName,
...slotVariants
} of compoundSlots) {
for (const slotName of slots) {
result[slotName] = result[slotName] || [];
result[slotName].push([slotClass, slotClassName]);
}

if (!isEmptyObject(slotVariants)) {
let isValid = true;

for (const key of Object.keys(slotVariants)) {
const completePropsValue = getCompleteProps(key, slotProps)[key];

if (completePropsValue === undefined || completePropsValue !== slotVariants[key]) {
// if the value is boolean, skip it
if (isBoolean(slotVariants[key])) {
break;
}

if (
completePropsValue === undefined ||
!slotVariants[key] ||
!slotVariants[key].includes(completePropsValue)
) {
isValid = false;
break;
}
Expand All @@ -368,6 +373,11 @@ export const tv = (options, configProp) => {
continue;
}
}

for (const slotName of slots) {
result[slotName] = result[slotName] || [];
result[slotName].push([slotClass, slotClassName]);
}
}

return result;
Expand Down
2 changes: 2 additions & 0 deletions src/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export declare const mergeObjects: (obj1: unknown, obj2: unknown) => unknown;
export declare const removeExtraSpaces: (str: string) => string;

export declare const isEqual: (obj1: object, obj2: object) => boolean;

export declare const isBoolean: (value: unknown) => boolean;
2 changes: 2 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export const isEmptyObject = (obj) =>

export const isEqual = (obj1, obj2) => JSON.stringify(obj1) === JSON.stringify(obj2);

export const isBoolean = (value) => typeof value === "boolean";

function flat(arr, target) {
arr.forEach(function (el) {
if (Array.isArray(el)) flat(el, target);
Expand Down

0 comments on commit a97aa84

Please sign in to comment.