fix: apply overload for vcn to remove preset in prop when preset is not defined

This commit is contained in:
p-sw 2024-05-25 21:31:24 +09:00
parent 0e153845a2
commit 1001090e4c

View File

@ -78,8 +78,8 @@ type VariantKV<V extends VariantType> = {
* } * }
* ``` * ```
*/ */
type PresetType<V extends VariantType, N extends string> = { type PresetType<V extends VariantType> = {
[PresetName in N]: Partial<VariantKV<V>> & { className?: string }; [PresetName: string]: Partial<VariantKV<V>> & { className?: string };
}; };
/** /**
@ -89,24 +89,15 @@ type PresetType<V extends VariantType, N extends string> = {
* @returns function (variantProps) -> class name, * @returns function (variantProps) -> class name,
* @returns function (anyProps) -> [variantProps, otherProps] * @returns function (anyProps) -> [variantProps, otherProps]
*/ */
export function vcn< export function vcn<V extends VariantType>(param: {
V extends VariantType,
N extends string /* Preset names */,
>({
base,
variants,
defaults,
presets,
}: {
base?: string | undefined; base?: string | undefined;
variants: V /* VariantType */; variants: V;
defaults: VariantKV<V>; defaults: VariantKV<V>;
presets?: PresetType<V, N>; presets?: undefined;
}): [ }): [
( (
variantProps: Partial<VariantKV<V>> & { variantProps: Partial<VariantKV<V>> & {
className?: string; className?: string;
preset?: N;
} }
) => string, ) => string,
<AnyPropBeforeResolve extends Record<string, any>>( <AnyPropBeforeResolve extends Record<string, any>>(
@ -114,14 +105,49 @@ export function vcn<
) => [ ) => [
Partial<VariantKV<V>> & { Partial<VariantKV<V>> & {
className?: string; className?: string;
preset?: N; },
Omit<AnyPropBeforeResolve, keyof Partial<VariantKV<V>> | "className">,
],
];
export function vcn<V extends VariantType, P extends PresetType<V>>(param: {
base?: string | undefined;
variants: V /* VariantType */;
defaults: VariantKV<V>;
presets: P;
}): [
(
variantProps: Partial<VariantKV<V>> & {
className?: string;
preset?: keyof P;
}
) => string,
<AnyPropBeforeResolve extends Record<string, any>>(
anyProps: AnyPropBeforeResolve
) => [
Partial<VariantKV<V>> & {
className?: string;
preset?: keyof P;
}, },
Omit< Omit<
AnyPropBeforeResolve, AnyPropBeforeResolve,
keyof Partial<VariantKV<V>> | "preset" | "className" keyof Partial<VariantKV<V>> | "preset" | "className"
>, >,
], ],
] { ];
export function vcn<
V extends VariantType,
P extends PresetType<V> | undefined,
>({
base,
variants,
defaults,
presets,
}: {
base?: string | undefined;
variants: V;
defaults: VariantKV<V>;
presets?: P;
}) {
return [ return [
/** /**
* Takes any props (including className), and returns the class name. * Takes any props (including className), and returns the class name.
@ -130,9 +156,13 @@ export function vcn<
* @param variantProps - The variant props including className. * @param variantProps - The variant props including className.
* @returns The class name. * @returns The class name.
*/ */
({ className, preset, ...variantProps }) => { ({
const currentPreset: PresetType<V, N>[N] | null = className,
presets && preset ? presets[preset] ?? null : null; preset,
...variantProps
}: { className?: string; preset?: keyof P } & Partial<VariantKV<V>>) => {
const currentPreset: P[keyof P] | null =
presets && preset ? (presets as NonNullable<P>)[preset] ?? null : null;
const presetVariantKeys: (keyof V)[] = Object.keys(currentPreset ?? {}); const presetVariantKeys: (keyof V)[] = Object.keys(currentPreset ?? {});
return twMerge( return twMerge(
base, base,
@ -142,13 +172,13 @@ export function vcn<
([variantKey, defaultValue]) => ([variantKey, defaultValue]) =>
variants[variantKey][ variants[variantKey][
(variantProps as unknown as Partial<VariantKV<V>>)[variantKey] ?? (variantProps as unknown as Partial<VariantKV<V>>)[variantKey] ??
(currentPreset !== null && (!!currentPreset && presetVariantKeys.includes(variantKey)
presetVariantKeys.includes(variantKey) ? (currentPreset as Partial<VariantKV<V>>)[variantKey] ??
? currentPreset[variantKey] ?? defaultValue defaultValue
: defaultValue) : defaultValue)
] ]
), ),
currentPreset?.className, // preset's classname comes after user's variant props? huh.. (currentPreset as Partial<VariantKV<V>> | null)?.className, // preset's classname comes after user's variant props? huh..
className className
); );
}, },
@ -160,7 +190,9 @@ export function vcn<
* @param anyProps - Any props that have passed to the component. * @param anyProps - Any props that have passed to the component.
* @returns [variantProps, otherProps] * @returns [variantProps, otherProps]
*/ */
(anyProps) => { <AnyPropBeforeResolve extends Record<string, any>>(
anyProps: AnyPropBeforeResolve
) => {
const variantKeys = Object.keys(variants) as (keyof V)[]; const variantKeys = Object.keys(variants) as (keyof V)[];
return Object.entries(anyProps).reduce( return Object.entries(anyProps).reduce(
@ -178,7 +210,7 @@ export function vcn<
) as [ ) as [
Partial<VariantKV<V>> & { Partial<VariantKV<V>> & {
className?: string; className?: string;
preset?: N; preset?: keyof P;
}, },
Omit< Omit<
typeof anyProps, typeof anyProps,