Skip to content

Commit

Permalink
feat: implement splitVariantProps to avoid unexpected className
Browse files Browse the repository at this point in the history
  • Loading branch information
malangcat committed Jan 3, 2025
1 parent adf3cef commit 17129d2
Show file tree
Hide file tree
Showing 75 changed files with 564 additions and 301 deletions.
13 changes: 8 additions & 5 deletions packages/react/src/utils/createStyleContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import clsx from "clsx";
import { createContext, forwardRef, useContext } from "react";

type Recipe<
Props extends Record<string, string | undefined>,
Props extends Record<string, string | boolean | undefined>,
Classnames extends Record<string, string>,
> = (props?: Props) => Classnames;
> = ((props?: Props) => Classnames) & {
splitVariantProps: <T extends Props>(props: T) => [Props, Omit<T, keyof Props>];
};

export function createStyleContext<
Props extends Record<string, string | undefined>,
Props extends Record<string, string | boolean | undefined>,
Classnames extends Record<string, string>,
>(recipe: Recipe<Props, Classnames>) {
const ClassNamesContext = createContext<Classnames | null>(null);
Expand Down Expand Up @@ -50,14 +52,15 @@ export function createStyleContext<

const StyledComponent = forwardRef<any, any>((innerProps, ref) => {
const props = { ...(defaultProps ?? {}), ...useProps(), ...innerProps } as any; // TODO: use Props type instead of any after implementing splitRecipeProps()
const classNames = recipe(props); // TODO: classNames are generated on all props; we have to split recipeProps and others. should be resolved in qvism.
const [variantProps, otherProps] = recipe.splitVariantProps(props);
const classNames = recipe(variantProps); // TODO: classNames are generated on all props; we have to split recipeProps and others. should be resolved in qvism.
const className = classNames[slot as keyof typeof classNames];

return (
<ClassNamesProvider value={classNames}>
{/* TODO: implement splitRecipeProps() method and spread splitted props */}
{/* @ts-ignore */}
<Component ref={ref} {...props} className={clsx(className, props.className)} />
<Component ref={ref} {...otherProps} className={clsx(className, props.className)} />
</ClassNamesProvider>
);
});
Expand Down
18 changes: 11 additions & 7 deletions packages/recipe/lib/actionButton.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface ActionButtonVariant {
declare interface ActionButtonVariant {
/**
* @default brandSolid
*/
Expand All @@ -13,16 +13,20 @@ interface ActionButtonVariant {
layout: "withText" | "iconOnly";
}

type ActionButtonVariantMap = {
declare type ActionButtonVariantMap = {
[key in keyof ActionButtonVariant]: Array<ActionButtonVariant[key]>;
};

export type ActionButtonVariantProps = Partial<ActionButtonVariant>;
export declare type ActionButtonVariantProps = Partial<ActionButtonVariant>;

export type ActionButtonSlotName = "root" | "label" | "icon" | "prefixIcon" | "suffixIcon" | "progressCircle";
export declare type ActionButtonSlotName = "root" | "label" | "icon" | "prefixIcon" | "suffixIcon" | "progressCircle";

export const actionButtonVariantMap: ActionButtonVariantMap;
export declare const actionButtonVariantMap: ActionButtonVariantMap;

export function actionButton(
export declare const actionButton: ((
props?: ActionButtonVariantProps,
): Record<ActionButtonSlotName, string>;
) => Record<ActionButtonSlotName, string>) & {
splitVariantProps: <T extends ActionButtonVariantProps>(
props: T,
) => [ActionButtonVariantProps, Omit<T, keyof ActionButtonVariantProps>];
}
5 changes: 4 additions & 1 deletion packages/recipe/lib/actionButton.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createClassName } from "./className.mjs";
import { mergeVariants } from "./mergeVariants.mjs";
import { splitVariantProps } from "./splitVariantProps.mjs";

const actionButtonSlotNames = [
[
Expand Down Expand Up @@ -101,4 +102,6 @@ export function actionButton(props) {
];
}),
);
}
}

Object.assign(actionButton, { splitVariantProps: (props) => splitVariantProps(props, actionButtonVariantMap) });
18 changes: 11 additions & 7 deletions packages/recipe/lib/actionChip.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface ActionChipVariant {
declare interface ActionChipVariant {
/**
* @default medium
*/
Expand All @@ -9,16 +9,20 @@ interface ActionChipVariant {
layout: "withText" | "iconOnly";
}

type ActionChipVariantMap = {
declare type ActionChipVariantMap = {
[key in keyof ActionChipVariant]: Array<ActionChipVariant[key]>;
};

export type ActionChipVariantProps = Partial<ActionChipVariant>;
export declare type ActionChipVariantProps = Partial<ActionChipVariant>;

export type ActionChipSlotName = "root" | "label" | "icon" | "prefixIcon" | "suffixIcon" | "count";
export declare type ActionChipSlotName = "root" | "label" | "icon" | "prefixIcon" | "suffixIcon" | "count";

export const actionChipVariantMap: ActionChipVariantMap;
export declare const actionChipVariantMap: ActionChipVariantMap;

export function actionChip(
export declare const actionChip: ((
props?: ActionChipVariantProps,
): Record<ActionChipSlotName, string>;
) => Record<ActionChipSlotName, string>) & {
splitVariantProps: <T extends ActionChipVariantProps>(
props: T,
) => [ActionChipVariantProps, Omit<T, keyof ActionChipVariantProps>];
}
5 changes: 4 additions & 1 deletion packages/recipe/lib/actionChip.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createClassName } from "./className.mjs";
import { mergeVariants } from "./mergeVariants.mjs";
import { splitVariantProps } from "./splitVariantProps.mjs";

const actionChipSlotNames = [
[
Expand Down Expand Up @@ -74,4 +75,6 @@ export function actionChip(props) {
];
}),
);
}
}

Object.assign(actionChip, { splitVariantProps: (props) => splitVariantProps(props, actionChipVariantMap) });
18 changes: 11 additions & 7 deletions packages/recipe/lib/actionSheet.d.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
interface ActionSheetVariant {
declare interface ActionSheetVariant {

}

type ActionSheetVariantMap = {
declare type ActionSheetVariantMap = {
[key in keyof ActionSheetVariant]: Array<ActionSheetVariant[key]>;
};

export type ActionSheetVariantProps = Partial<ActionSheetVariant>;
export declare type ActionSheetVariantProps = Partial<ActionSheetVariant>;

export type ActionSheetSlotName = "backdrop" | "container" | "content" | "list" | "group" | "footer";
export declare type ActionSheetSlotName = "backdrop" | "container" | "content" | "list" | "group" | "footer";

export const actionSheetVariantMap: ActionSheetVariantMap;
export declare const actionSheetVariantMap: ActionSheetVariantMap;

export function actionSheet(
export declare const actionSheet: ((
props?: ActionSheetVariantProps,
): Record<ActionSheetSlotName, string>;
) => Record<ActionSheetSlotName, string>) & {
splitVariantProps: <T extends ActionSheetVariantProps>(
props: T,
) => [ActionSheetVariantProps, Omit<T, keyof ActionSheetVariantProps>];
}
5 changes: 4 additions & 1 deletion packages/recipe/lib/actionSheet.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createClassName } from "./className.mjs";
import { mergeVariants } from "./mergeVariants.mjs";
import { splitVariantProps } from "./splitVariantProps.mjs";

const actionSheetSlotNames = [
[
Expand Down Expand Up @@ -45,4 +46,6 @@ export function actionSheet(props) {
];
}),
);
}
}

Object.assign(actionSheet, { splitVariantProps: (props) => splitVariantProps(props, actionSheetVariantMap) });
18 changes: 11 additions & 7 deletions packages/recipe/lib/actionSheetCloseButton.d.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
interface ActionSheetCloseButtonVariant {
declare interface ActionSheetCloseButtonVariant {

}

type ActionSheetCloseButtonVariantMap = {
declare type ActionSheetCloseButtonVariantMap = {
[key in keyof ActionSheetCloseButtonVariant]: Array<ActionSheetCloseButtonVariant[key]>;
};

export type ActionSheetCloseButtonVariantProps = Partial<ActionSheetCloseButtonVariant>;
export declare type ActionSheetCloseButtonVariantProps = Partial<ActionSheetCloseButtonVariant>;

export type ActionSheetCloseButtonSlotName = "root" | "label";
export declare type ActionSheetCloseButtonSlotName = "root" | "label";

export const actionSheetCloseButtonVariantMap: ActionSheetCloseButtonVariantMap;
export declare const actionSheetCloseButtonVariantMap: ActionSheetCloseButtonVariantMap;

export function actionSheetCloseButton(
export declare const actionSheetCloseButton: ((
props?: ActionSheetCloseButtonVariantProps,
): Record<ActionSheetCloseButtonSlotName, string>;
) => Record<ActionSheetCloseButtonSlotName, string>) & {
splitVariantProps: <T extends ActionSheetCloseButtonVariantProps>(
props: T,
) => [ActionSheetCloseButtonVariantProps, Omit<T, keyof ActionSheetCloseButtonVariantProps>];
}
5 changes: 4 additions & 1 deletion packages/recipe/lib/actionSheetCloseButton.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createClassName } from "./className.mjs";
import { mergeVariants } from "./mergeVariants.mjs";
import { splitVariantProps } from "./splitVariantProps.mjs";

const actionSheetCloseButtonSlotNames = [
[
Expand Down Expand Up @@ -29,4 +30,6 @@ export function actionSheetCloseButton(props) {
];
}),
);
}
}

Object.assign(actionSheetCloseButton, { splitVariantProps: (props) => splitVariantProps(props, actionSheetCloseButtonVariantMap) });
18 changes: 11 additions & 7 deletions packages/recipe/lib/actionSheetItem.d.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
interface ActionSheetItemVariant {
declare interface ActionSheetItemVariant {
/**
* @default neutral
*/
tone: "neutral" | "danger";
}

type ActionSheetItemVariantMap = {
declare type ActionSheetItemVariantMap = {
[key in keyof ActionSheetItemVariant]: Array<ActionSheetItemVariant[key]>;
};

export type ActionSheetItemVariantProps = Partial<ActionSheetItemVariant>;
export declare type ActionSheetItemVariantProps = Partial<ActionSheetItemVariant>;

export type ActionSheetItemSlotName = "root" | "prefixIcon" | "label";
export declare type ActionSheetItemSlotName = "root" | "prefixIcon" | "label";

export const actionSheetItemVariantMap: ActionSheetItemVariantMap;
export declare const actionSheetItemVariantMap: ActionSheetItemVariantMap;

export function actionSheetItem(
export declare const actionSheetItem: ((
props?: ActionSheetItemVariantProps,
): Record<ActionSheetItemSlotName, string>;
) => Record<ActionSheetItemSlotName, string>) & {
splitVariantProps: <T extends ActionSheetItemVariantProps>(
props: T,
) => [ActionSheetItemVariantProps, Omit<T, keyof ActionSheetItemVariantProps>];
}
5 changes: 4 additions & 1 deletion packages/recipe/lib/actionSheetItem.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createClassName } from "./className.mjs";
import { mergeVariants } from "./mergeVariants.mjs";
import { splitVariantProps } from "./splitVariantProps.mjs";

const actionSheetItemSlotNames = [
[
Expand Down Expand Up @@ -40,4 +41,6 @@ export function actionSheetItem(props) {
];
}),
);
}
}

Object.assign(actionSheetItem, { splitVariantProps: (props) => splitVariantProps(props, actionSheetItemVariantMap) });
18 changes: 11 additions & 7 deletions packages/recipe/lib/avatar.d.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
interface AvatarVariant {
declare interface AvatarVariant {
/**
* @default 48
*/
size: "20" | "24" | "36" | "48" | "64" | "80" | "96";
}

type AvatarVariantMap = {
declare type AvatarVariantMap = {
[key in keyof AvatarVariant]: Array<AvatarVariant[key]>;
};

export type AvatarVariantProps = Partial<AvatarVariant>;
export declare type AvatarVariantProps = Partial<AvatarVariant>;

export type AvatarSlotName = "root" | "image" | "fallback" | "badge";
export declare type AvatarSlotName = "root" | "image" | "fallback" | "badge";

export const avatarVariantMap: AvatarVariantMap;
export declare const avatarVariantMap: AvatarVariantMap;

export function avatar(
export declare const avatar: ((
props?: AvatarVariantProps,
): Record<AvatarSlotName, string>;
) => Record<AvatarSlotName, string>) & {
splitVariantProps: <T extends AvatarVariantProps>(
props: T,
) => [AvatarVariantProps, Omit<T, keyof AvatarVariantProps>];
}
5 changes: 4 additions & 1 deletion packages/recipe/lib/avatar.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createClassName } from "./className.mjs";
import { mergeVariants } from "./mergeVariants.mjs";
import { splitVariantProps } from "./splitVariantProps.mjs";

const avatarSlotNames = [
[
Expand Down Expand Up @@ -49,4 +50,6 @@ export function avatar(props) {
];
}),
);
}
}

Object.assign(avatar, { splitVariantProps: (props) => splitVariantProps(props, avatarVariantMap) });
18 changes: 11 additions & 7 deletions packages/recipe/lib/avatarStack.d.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
interface AvatarStackVariant {
declare interface AvatarStackVariant {
/**
* @default 48
*/
size: "20" | "24" | "36" | "48" | "64";
}

type AvatarStackVariantMap = {
declare type AvatarStackVariantMap = {
[key in keyof AvatarStackVariant]: Array<AvatarStackVariant[key]>;
};

export type AvatarStackVariantProps = Partial<AvatarStackVariant>;
export declare type AvatarStackVariantProps = Partial<AvatarStackVariant>;

export type AvatarStackSlotName = "root" | "item";
export declare type AvatarStackSlotName = "root" | "item";

export const avatarStackVariantMap: AvatarStackVariantMap;
export declare const avatarStackVariantMap: AvatarStackVariantMap;

export function avatarStack(
export declare const avatarStack: ((
props?: AvatarStackVariantProps,
): Record<AvatarStackSlotName, string>;
) => Record<AvatarStackSlotName, string>) & {
splitVariantProps: <T extends AvatarStackVariantProps>(
props: T,
) => [AvatarStackVariantProps, Omit<T, keyof AvatarStackVariantProps>];
}
5 changes: 4 additions & 1 deletion packages/recipe/lib/avatarStack.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createClassName } from "./className.mjs";
import { mergeVariants } from "./mergeVariants.mjs";
import { splitVariantProps } from "./splitVariantProps.mjs";

const avatarStackSlotNames = [
[
Expand Down Expand Up @@ -39,4 +40,6 @@ export function avatarStack(props) {
];
}),
);
}
}

Object.assign(avatarStack, { splitVariantProps: (props) => splitVariantProps(props, avatarStackVariantMap) });
Loading

0 comments on commit 17129d2

Please sign in to comment.