responsive-class-variants 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -56,7 +56,7 @@ type ResponsiveClassesConfig<T extends VariantConfig, B extends string> = {
56
56
  base: string;
57
57
  variants?: T;
58
58
  compoundVariants?: Partial<VariantProps<T, B>>[];
59
- onComplete?: (classes: string) => void;
59
+ onComplete?: (classes: string) => string;
60
60
  };
61
61
  /**
62
62
  * Creates a function that generates classes based on variant configurations and responsive props
@@ -71,7 +71,7 @@ type ResponsiveClassesConfig<T extends VariantConfig, B extends string> = {
71
71
  * or an object with true/false keys for boolean variants
72
72
  * @param config.compoundVariants - Optional array of compound variants that apply additional classes
73
73
  * when multiple variants have specific values
74
- * @param config.onComplete - Optional callback function that receives the generated classes
74
+ * @param config.onComplete - Optional callback function that receives the generated classes and returns the final classes
75
75
  *
76
76
  * @returns A function that accepts variant props and returns classes with twMerge
77
77
  *
@@ -98,13 +98,13 @@ type ResponsiveClassesConfig<T extends VariantConfig, B extends string> = {
98
98
  * // Or with responsive values:
99
99
  * getButtonVariants({ intent: { initial: "primary", md: "secondary" } })
100
100
  */
101
- export declare const rcv: <T extends VariantConfig, B extends string = DefaultBreakpoints>({ base, variants, compoundVariants, onComplete, }: ResponsiveClassesConfig<T, B>) => ({ className, ...props }: VariantProps<T, B>) => string | void;
101
+ export declare const rcv: <T extends VariantConfig, B extends string = DefaultBreakpoints>({ base, variants, compoundVariants, onComplete, }: ResponsiveClassesConfig<T, B>) => ({ className, ...props }: VariantProps<T, B>) => string;
102
102
  /**
103
103
  * Creates a custom rcv function with custom breakpoints and an optional onComplete callback
104
104
  *
105
105
  * @template B - The custom breakpoints type
106
- * @param breakpoints - Array of custom breakpoint names
107
- * @param onComplete - Optional callback function that receives the generated classes
106
+ * @param breakpoints - Optional array of custom breakpoint names
107
+ * @param onComplete - Optional callback function that receives the generated classes and returns the final classes
108
108
  * @returns A function that creates rcv with custom breakpoints
109
109
  *
110
110
  * @example
@@ -123,5 +123,5 @@ export declare const rcv: <T extends VariantConfig, B extends string = DefaultBr
123
123
  * // Usage with custom breakpoints:
124
124
  * getButtonVariants({ intent: { initial: "primary", mobile: "secondary", desktop: "primary" } })
125
125
  */
126
- export declare const createRcv: <B extends string>(_breakpoints: readonly B[], onComplete?: (classes: string) => void) => <T extends VariantConfig>(config: ResponsiveClassesConfig<T, B>) => ({ className, ...props }: VariantProps<T, B>) => string | void;
126
+ export declare const createRcv: <B extends string>(_breakpoints?: readonly B[], onComplete?: (classes: string) => string) => <T extends VariantConfig>(config: ResponsiveClassesConfig<T, B>) => ({ className, ...props }: VariantProps<T, B>) => string;
127
127
  export {};
package/dist/index.js CHANGED
@@ -52,7 +52,7 @@ export const mapResponsiveValue = (value, mapper) => isSingularValue(value)
52
52
  * or an object with true/false keys for boolean variants
53
53
  * @param config.compoundVariants - Optional array of compound variants that apply additional classes
54
54
  * when multiple variants have specific values
55
- * @param config.onComplete - Optional callback function that receives the generated classes
55
+ * @param config.onComplete - Optional callback function that receives the generated classes and returns the final classes
56
56
  *
57
57
  * @returns A function that accepts variant props and returns classes with twMerge
58
58
  *
@@ -124,8 +124,8 @@ export const rcv = ({ base, variants, compoundVariants, onComplete, }) => ({ cla
124
124
  * Creates a custom rcv function with custom breakpoints and an optional onComplete callback
125
125
  *
126
126
  * @template B - The custom breakpoints type
127
- * @param breakpoints - Array of custom breakpoint names
128
- * @param onComplete - Optional callback function that receives the generated classes
127
+ * @param breakpoints - Optional array of custom breakpoint names
128
+ * @param onComplete - Optional callback function that receives the generated classes and returns the final classes
129
129
  * @returns A function that creates rcv with custom breakpoints
130
130
  *
131
131
  * @example
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"/","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { clsx } from \"clsx\";\n\nexport type DefaultBreakpoints = \"sm\" | \"md\" | \"lg\" | \"xl\";\nexport type Breakpoints = DefaultBreakpoints;\n\nexport type BreakpointsMap<V, B extends string = DefaultBreakpoints> = {\n\tinitial: V;\n} & Partial<{\n\t[breakpoint in B]: V;\n}>;\n\nexport type ResponsiveValue<T, B extends string = DefaultBreakpoints> =\n\t| T\n\t| BreakpointsMap<T, B>;\n\nconst isSingularValue = <A, B extends string>(\n\tvalue: ResponsiveValue<A, B>,\n): value is A => !isBreakpointsMap(value);\n\nconst isBreakpointsMap = <A, B extends string>(\n\tvalue: ResponsiveValue<A, B>,\n): value is BreakpointsMap<A, B> =>\n\ttypeof value === \"object\" && value != null && !Array.isArray(value);\n\n/**\n * Maps a ResponsiveValue to a new ResponsiveValue using the provided mapper function. Singular values are passed through as is.\n *\n * @template V The type of the original value\n * @template T The type of the mapped value\n * @template B The type of breakpoints\n * @param {ResponsiveValue<V, B>} value - The original ResponsiveValue to be mapped\n * @param {function(V): T} mapper - A function that maps a ResponsiveValue to a new ResponsiveValue\n * @returns {ResponsiveValue<T, B>} A new ResponsiveValue with the mapped values\n *\n *\n * @example\n * const sizes = {\n * initial: 'md',\n * sm: 'lg',\n * }\n *\n * const output = mapResponsiveValue(sizes, size => {\n *\tswitch (size) {\n *\t\tcase 'initial':\n *\t\treturn 'sm';\n *\t\tcase 'sm':\n *\t\t\treturn 'md';\n *\t\t}\n *\t});\n *\n * // console.log(output)\n * {\n *\tinitial: 'sm',\n *\tsm: 'md',\n * }\n */\nexport const mapResponsiveValue = <V, T, B extends string = DefaultBreakpoints>(\n\tvalue: ResponsiveValue<V, B>,\n\tmapper: (value: V) => T,\n): ResponsiveValue<T, B> =>\n\tisSingularValue(value)\n\t\t? mapper(value)\n\t\t: (Object.fromEntries(\n\t\t\t\tObject.entries(value).map(([breakpoint, value]) => [\n\t\t\t\t\tbreakpoint,\n\t\t\t\t\tmapper(value),\n\t\t\t\t]),\n\t\t\t) as BreakpointsMap<T, B>);\n\n/**\n * Start of rcv and types\n */\n\ntype VariantValue = Record<string, string>;\ntype VariantConfig = Record<string, VariantValue>;\n\ntype StringBoolean = \"true\" | \"false\";\ntype BooleanVariant = Partial<Record<StringBoolean, string>>;\n\ntype VariantPropValue<T, B extends string> = T extends BooleanVariant\n\t? ResponsiveValue<boolean, B> | undefined\n\t: T extends Record<string, unknown>\n\t\t? ResponsiveValue<keyof T, B>\n\t\t: never;\n\ntype VariantProps<T extends VariantConfig, B extends string> = {\n\t[K in keyof T]: VariantPropValue<T[K], B>;\n} & {\n\tclassName?: string;\n};\n\ntype ResponsiveClassesConfig<T extends VariantConfig, B extends string> = {\n\tbase: string;\n\tvariants?: T;\n\tcompoundVariants?: Partial<VariantProps<T, B>>[];\n\tonComplete?: (classes: string) => void;\n};\n\n/**\n * Creates a function that generates classes based on variant configurations and responsive props\n *\n * @template T - Type extending VariantConfig (Record of variant names to their possible values and corresponding classes)\n * @template B - The breakpoints type\n *\n * @param config - Configuration object for variants\n * @param config.base - Base classes that are always applied\n * @param config.variants - Object containing variant definitions where each key is a variant name\n * and value is either a string of class names, an object mapping variant values to class names,\n * or an object with true/false keys for boolean variants\n * @param config.compoundVariants - Optional array of compound variants that apply additional classes\n * when multiple variants have specific values\n * @param config.onComplete - Optional callback function that receives the generated classes\n *\n * @returns A function that accepts variant props and returns classes with twMerge\n *\n * @example\n * const getButtonVariants = rcv({\n * base: \"px-4 py-2 rounded\",\n * variants: {\n * intent: {\n * primary: \"bg-blue-500 text-white\",\n * secondary: \"bg-gray-200 text-gray-800\"\n * },\n * size: {\n * sm: \"text-sm\",\n * lg: \"text-lg\"\n * },\n * disabled: {\n * true: \"opacity-50 cursor-not-allowed\"\n * }\n * }\n * });\n *\n * // Usage:\n * getButtonVariants({ intent: \"primary\", size: \"lg\", disabled: true })\n * // Or with responsive values:\n * getButtonVariants({ intent: { initial: \"primary\", md: \"secondary\" } })\n */\nexport const rcv =\n\t<T extends VariantConfig, B extends string = DefaultBreakpoints>({\n\t\tbase,\n\t\tvariants,\n\t\tcompoundVariants,\n\t\tonComplete,\n\t}: ResponsiveClassesConfig<T, B>) =>\n\t({ className, ...props }: VariantProps<T, B>) => {\n\t\tconst responsiveClasses = Object.entries(props)\n\t\t\t.map(([key, propValue]: [keyof T, VariantPropValue<T[keyof T], B>]) => {\n\t\t\t\tconst variant = variants?.[key];\n\t\t\t\tconst value =\n\t\t\t\t\ttypeof propValue === \"boolean\" ? String(propValue) : propValue;\n\n\t\t\t\t// Handle undefined values\n\t\t\t\tif (!value) return undefined;\n\n\t\t\t\tconst variantValue = variant?.[value as keyof VariantValue];\n\n\t\t\t\t// Handle string values\n\t\t\t\tif (typeof variantValue === \"string\") {\n\t\t\t\t\treturn variantValue;\n\t\t\t\t}\n\n\t\t\t\t// Handle responsive values\n\t\t\t\treturn Object.entries(value as Partial<BreakpointsMap<T, B>>)\n\t\t\t\t\t.map(([breakpoint, value]) => {\n\t\t\t\t\t\t// If the breakpoint is initial, return the variant value without breakpoint prefix\n\t\t\t\t\t\tif (breakpoint === \"initial\") {\n\t\t\t\t\t\t\treturn variants?.[key]?.[value as keyof typeof variant];\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Otherwise, return the variant value with the breakpoint prefix\n\t\t\t\t\t\treturn variants?.[key]?.[value as keyof typeof variant]\n\t\t\t\t\t\t\t?.split(\" \")\n\t\t\t\t\t\t\t.map((className) => `${breakpoint}:${className}`)\n\t\t\t\t\t\t\t.join(\" \");\n\t\t\t\t\t})\n\t\t\t\t\t.join(\" \");\n\t\t\t})\n\t\t\t.filter(Boolean)\n\t\t\t.join(\" \");\n\n\t\tconst compoundClasses = compoundVariants\n\t\t\t?.map(({ className, ...compound }) => {\n\t\t\t\tif (\n\t\t\t\t\tObject.entries(compound).every(\n\t\t\t\t\t\t([key, value]) =>\n\t\t\t\t\t\t\tprops[key] === String(value) || props[key] === value,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn className;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t})\n\t\t\t.filter(Boolean);\n\n\t\tconst classes = clsx(base, responsiveClasses, compoundClasses, className);\n\t\treturn onComplete ? onComplete(classes) : classes;\n\t};\n\n/**\n * Creates a custom rcv function with custom breakpoints and an optional onComplete callback\n *\n * @template B - The custom breakpoints type\n * @param breakpoints - Array of custom breakpoint names\n * @param onComplete - Optional callback function that receives the generated classes\n * @returns A function that creates rcv with custom breakpoints\n *\n * @example\n * const customRcv = createRcv(['mobile', 'tablet', 'desktop']);\n *\n * const getButtonVariants = customRcv({\n * base: \"px-4 py-2 rounded\",\n * variants: {\n * intent: {\n * primary: \"bg-blue-500 text-white\",\n * secondary: \"bg-gray-200 text-gray-800\"\n * }\n * }\n * });\n *\n * // Usage with custom breakpoints:\n * getButtonVariants({ intent: { initial: \"primary\", mobile: \"secondary\", desktop: \"primary\" } })\n */\n\nexport const createRcv = <B extends string>(\n\t_breakpoints: readonly B[],\n\tonComplete?: (classes: string) => void,\n) => {\n\treturn <T extends VariantConfig>(config: ResponsiveClassesConfig<T, B>) =>\n\t\trcv<T, B>({ ...config, onComplete });\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"/","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAe5B,MAAM,eAAe,GAAG,CACvB,KAA4B,EACf,EAAE,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAE1C,MAAM,gBAAgB,GAAG,CACxB,KAA4B,EACI,EAAE,CAClC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CACjC,KAA4B,EAC5B,MAAuB,EACC,EAAE,CAC1B,eAAe,CAAC,KAAK,CAAC;IACrB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;IACf,CAAC,CAAE,MAAM,CAAC,WAAW,CACnB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;QAClD,UAAU;QACV,MAAM,CAAC,KAAK,CAAC;KACb,CAAC,CACuB,CAAC;AA+B9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,MAAM,GAAG,GACf,CAAiE,EAChE,IAAI,EACJ,QAAQ,EACR,gBAAgB,EAChB,UAAU,GACqB,EAAE,EAAE,CACpC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAsB,EAAE,EAAE;IAC/C,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;SAC7C,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,CAA6C,EAAE,EAAE;QACrE,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,KAAK,GACV,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEhE,0BAA0B;QAC1B,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAE7B,MAAM,YAAY,GAAG,OAAO,EAAE,CAAC,KAA2B,CAAC,CAAC;QAE5D,uBAAuB;QACvB,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,YAAY,CAAC;QACrB,CAAC;QAED,2BAA2B;QAC3B,OAAO,MAAM,CAAC,OAAO,CAAC,KAAsC,CAAC;aAC3D,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,EAAE;YAC5B,mFAAmF;YACnF,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAA6B,CAAC,CAAC;YACzD,CAAC;YACD,iEAAiE;YACjE,OAAO,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAA6B,CAAC;gBACtD,EAAE,KAAK,CAAC,GAAG,CAAC;iBACX,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,UAAU,IAAI,SAAS,EAAE,CAAC;iBAChD,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,CAAC,CAAC;SACD,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,MAAM,eAAe,GAAG,gBAAgB;QACvC,EAAE,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,QAAQ,EAAE,EAAE,EAAE;QACpC,IACC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAC7B,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAChB,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CACrD,EACA,CAAC;YACF,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC,CAAC;SACD,MAAM,CAAC,OAAO,CAAC,CAAC;IAElB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,iBAAiB,EAAE,eAAe,EAAE,SAAS,CAAC,CAAC;IAC1E,OAAO,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACnD,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,CACxB,YAA2B,EAC3B,UAAwC,EACvC,EAAE;IACH,OAAO,CAA0B,MAAqC,EAAE,EAAE,CACzE,GAAG,CAAO,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AACvC,CAAC,CAAC","sourcesContent":["import { clsx } from \"clsx\";\n\nexport type DefaultBreakpoints = \"sm\" | \"md\" | \"lg\" | \"xl\";\nexport type Breakpoints = DefaultBreakpoints;\n\nexport type BreakpointsMap<V, B extends string = DefaultBreakpoints> = {\n\tinitial: V;\n} & Partial<{\n\t[breakpoint in B]: V;\n}>;\n\nexport type ResponsiveValue<T, B extends string = DefaultBreakpoints> =\n\t| T\n\t| BreakpointsMap<T, B>;\n\nconst isSingularValue = <A, B extends string>(\n\tvalue: ResponsiveValue<A, B>,\n): value is A => !isBreakpointsMap(value);\n\nconst isBreakpointsMap = <A, B extends string>(\n\tvalue: ResponsiveValue<A, B>,\n): value is BreakpointsMap<A, B> =>\n\ttypeof value === \"object\" && value != null && !Array.isArray(value);\n\n/**\n * Maps a ResponsiveValue to a new ResponsiveValue using the provided mapper function. Singular values are passed through as is.\n *\n * @template V The type of the original value\n * @template T The type of the mapped value\n * @template B The type of breakpoints\n * @param {ResponsiveValue<V, B>} value - The original ResponsiveValue to be mapped\n * @param {function(V): T} mapper - A function that maps a ResponsiveValue to a new ResponsiveValue\n * @returns {ResponsiveValue<T, B>} A new ResponsiveValue with the mapped values\n *\n *\n * @example\n * const sizes = {\n * initial: 'md',\n * sm: 'lg',\n * }\n *\n * const output = mapResponsiveValue(sizes, size => {\n *\tswitch (size) {\n *\t\tcase 'initial':\n *\t\treturn 'sm';\n *\t\tcase 'sm':\n *\t\t\treturn 'md';\n *\t\t}\n *\t});\n *\n * // console.log(output)\n * {\n *\tinitial: 'sm',\n *\tsm: 'md',\n * }\n */\nexport const mapResponsiveValue = <V, T, B extends string = DefaultBreakpoints>(\n\tvalue: ResponsiveValue<V, B>,\n\tmapper: (value: V) => T,\n): ResponsiveValue<T, B> =>\n\tisSingularValue(value)\n\t\t? mapper(value)\n\t\t: (Object.fromEntries(\n\t\t\t\tObject.entries(value).map(([breakpoint, value]) => [\n\t\t\t\t\tbreakpoint,\n\t\t\t\t\tmapper(value),\n\t\t\t\t]),\n\t\t\t) as BreakpointsMap<T, B>);\n\n/**\n * Start of rcv and types\n */\n\ntype VariantValue = Record<string, string>;\ntype VariantConfig = Record<string, VariantValue>;\n\ntype StringBoolean = \"true\" | \"false\";\ntype BooleanVariant = Partial<Record<StringBoolean, string>>;\n\ntype VariantPropValue<T, B extends string> = T extends BooleanVariant\n\t? ResponsiveValue<boolean, B> | undefined\n\t: T extends Record<string, unknown>\n\t\t? ResponsiveValue<keyof T, B>\n\t\t: never;\n\ntype VariantProps<T extends VariantConfig, B extends string> = {\n\t[K in keyof T]: VariantPropValue<T[K], B>;\n} & {\n\tclassName?: string;\n};\n\ntype ResponsiveClassesConfig<T extends VariantConfig, B extends string> = {\n\tbase: string;\n\tvariants?: T;\n\tcompoundVariants?: Partial<VariantProps<T, B>>[];\n\tonComplete?: (classes: string) => string;\n};\n\n/**\n * Creates a function that generates classes based on variant configurations and responsive props\n *\n * @template T - Type extending VariantConfig (Record of variant names to their possible values and corresponding classes)\n * @template B - The breakpoints type\n *\n * @param config - Configuration object for variants\n * @param config.base - Base classes that are always applied\n * @param config.variants - Object containing variant definitions where each key is a variant name\n * and value is either a string of class names, an object mapping variant values to class names,\n * or an object with true/false keys for boolean variants\n * @param config.compoundVariants - Optional array of compound variants that apply additional classes\n * when multiple variants have specific values\n * @param config.onComplete - Optional callback function that receives the generated classes and returns the final classes\n *\n * @returns A function that accepts variant props and returns classes with twMerge\n *\n * @example\n * const getButtonVariants = rcv({\n * base: \"px-4 py-2 rounded\",\n * variants: {\n * intent: {\n * primary: \"bg-blue-500 text-white\",\n * secondary: \"bg-gray-200 text-gray-800\"\n * },\n * size: {\n * sm: \"text-sm\",\n * lg: \"text-lg\"\n * },\n * disabled: {\n * true: \"opacity-50 cursor-not-allowed\"\n * }\n * }\n * });\n *\n * // Usage:\n * getButtonVariants({ intent: \"primary\", size: \"lg\", disabled: true })\n * // Or with responsive values:\n * getButtonVariants({ intent: { initial: \"primary\", md: \"secondary\" } })\n */\nexport const rcv =\n\t<T extends VariantConfig, B extends string = DefaultBreakpoints>({\n\t\tbase,\n\t\tvariants,\n\t\tcompoundVariants,\n\t\tonComplete,\n\t}: ResponsiveClassesConfig<T, B>) =>\n\t({ className, ...props }: VariantProps<T, B>) => {\n\t\tconst responsiveClasses = Object.entries(props)\n\t\t\t.map(([key, propValue]: [keyof T, VariantPropValue<T[keyof T], B>]) => {\n\t\t\t\tconst variant = variants?.[key];\n\t\t\t\tconst value =\n\t\t\t\t\ttypeof propValue === \"boolean\" ? String(propValue) : propValue;\n\n\t\t\t\t// Handle undefined values\n\t\t\t\tif (!value) return undefined;\n\n\t\t\t\tconst variantValue = variant?.[value as keyof VariantValue];\n\n\t\t\t\t// Handle string values\n\t\t\t\tif (typeof variantValue === \"string\") {\n\t\t\t\t\treturn variantValue;\n\t\t\t\t}\n\n\t\t\t\t// Handle responsive values\n\t\t\t\treturn Object.entries(value as Partial<BreakpointsMap<T, B>>)\n\t\t\t\t\t.map(([breakpoint, value]) => {\n\t\t\t\t\t\t// If the breakpoint is initial, return the variant value without breakpoint prefix\n\t\t\t\t\t\tif (breakpoint === \"initial\") {\n\t\t\t\t\t\t\treturn variants?.[key]?.[value as keyof typeof variant];\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Otherwise, return the variant value with the breakpoint prefix\n\t\t\t\t\t\treturn variants?.[key]?.[value as keyof typeof variant]\n\t\t\t\t\t\t\t?.split(\" \")\n\t\t\t\t\t\t\t.map((className) => `${breakpoint}:${className}`)\n\t\t\t\t\t\t\t.join(\" \");\n\t\t\t\t\t})\n\t\t\t\t\t.join(\" \");\n\t\t\t})\n\t\t\t.filter(Boolean)\n\t\t\t.join(\" \");\n\n\t\tconst compoundClasses = compoundVariants\n\t\t\t?.map(({ className, ...compound }) => {\n\t\t\t\tif (\n\t\t\t\t\tObject.entries(compound).every(\n\t\t\t\t\t\t([key, value]) =>\n\t\t\t\t\t\t\tprops[key] === String(value) || props[key] === value,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn className;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t})\n\t\t\t.filter(Boolean);\n\n\t\tconst classes = clsx(base, responsiveClasses, compoundClasses, className);\n\t\treturn onComplete ? onComplete(classes) : classes;\n\t};\n\n/**\n * Creates a custom rcv function with custom breakpoints and an optional onComplete callback\n *\n * @template B - The custom breakpoints type\n * @param breakpoints - Optional array of custom breakpoint names\n * @param onComplete - Optional callback function that receives the generated classes and returns the final classes\n * @returns A function that creates rcv with custom breakpoints\n *\n * @example\n * const customRcv = createRcv(['mobile', 'tablet', 'desktop']);\n *\n * const getButtonVariants = customRcv({\n * base: \"px-4 py-2 rounded\",\n * variants: {\n * intent: {\n * primary: \"bg-blue-500 text-white\",\n * secondary: \"bg-gray-200 text-gray-800\"\n * }\n * }\n * });\n *\n * // Usage with custom breakpoints:\n * getButtonVariants({ intent: { initial: \"primary\", mobile: \"secondary\", desktop: \"primary\" } })\n */\n\nexport const createRcv = <B extends string>(\n\t_breakpoints?: readonly B[],\n\tonComplete?: (classes: string) => string,\n) => {\n\treturn <T extends VariantConfig>(config: ResponsiveClassesConfig<T, B>) =>\n\t\trcv<T, B>({ ...config, onComplete });\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "responsive-class-variants",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "rcv helps you create responsive class variants",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",