native-variants
Version:
A library for handling variants in React Native components with theme support.
215 lines (214 loc) • 9.18 kB
TypeScript
import type { Base, ColorSchemeConfig, Config, ConfigWithUtils, DefaultVariants, DefaultVariantsWithUtils, UtilsConfig, Variants, VariantsWithUtils } from "../types.js";
import { tailwindColors, tailwindSpacing, tailwindFontSizes, tailwindRadii, tailwindShadows, tailwindZIndex, tailwindOpacity, tailwindLineHeights, tailwindFontWeights, tailwindLetterSpacing, tailwindBorderWidths, tailwindDurations } from "../tokens/default-tokens.js";
/**
* Creates a styled component function with variant support.
* Provides caching for optimal performance in React Native.
*
* @template S - Union type of slot names
* @template V - Variants configuration type
*
* @param config - The styled component configuration
* @returns A function that computes styles based on variant props
*
* @example
* ```ts
* const buttonStyles = styled({
* slots: ["root", "text"],
* base: {
* root: { padding: 16 },
* text: { fontSize: 14 }
* },
* variants: {
* size: {
* small: { root: { padding: 8 } },
* large: { root: { padding: 24 } }
* }
* },
* defaultVariants: {
* size: "small"
* }
* });
*
* // Usage
* const styles = buttonStyles({ size: "large" });
* ```
*/
export declare function styled<const S extends string, V extends Variants<S>>(config: Config<S, V>): (props?: DefaultVariants<S, V>) => Base<S>;
/**
* Validates that two record types have the same keys.
* Returns true type if valid, error message type if not.
*/
type ValidateColorKeys<D extends Record<string, string>, K extends Record<string, string>> = Exclude<keyof K, keyof D> extends never ? Exclude<keyof D, keyof K> extends never ? true : {
_error: "⚠️ 'dark' is missing colors that exist in 'default'";
missingInDark: Exclude<keyof D, keyof K>;
} : {
_error: "⚠️ 'default' is missing colors that exist in 'dark'";
missingInDefault: Exclude<keyof K, keyof D>;
};
/**
* Theme configuration input for createNVA.
* Colors must have matching keys in default and dark.
*/
interface CreateNVATheme<D extends Record<string, string>, K extends Record<string, string>> {
colors: {
/** Light theme colors (default) */
default: D;
/** Dark theme colors - must have exactly the same keys as default */
dark: ValidateColorKeys<D, K> extends true ? K : ValidateColorKeys<D, K>;
};
}
/**
* Creates a themed NVA (Native Variants API) instance.
* Provides a styled function with access to theme tokens and custom utils.
*
* Colors support light/dark mode via `default` and `dark` keys.
* Both must have the same color keys for type safety - TypeScript will
* error if dark is missing any keys from default or vice versa.
*
* Utils are style shortcuts that expand to multiple CSS properties.
* They work like Stitches utils - you define them once and use them
* throughout your styles.
*
* Tailwind CSS tokens (spacing, fontSizes, radii, etc.) are included by default.
*
* @template D - Default colors type (inferred from colors.default)
* @template K - Dark colors type (must have same keys as D)
* @template U - Utils configuration type
*
* @param options - Configuration options
* @param options.theme - Theme configuration with colors (default/dark)
* @param options.utils - Custom style utilities (like Stitches)
* @returns An object containing the flattened theme, styled function, and utils
*
* @example
* ```ts
* const { styled, theme, colorScheme, utils } = createNVA({
* theme: {
* colors: {
* default: {
* primary: "#007AFF",
* background: "#FFFFFF",
* },
* dark: {
* primary: "#0A84FF",
* background: "#000000",
* },
* },
* },
* utils: {
* // Margin shortcuts
* mx: (value) => ({ marginLeft: value, marginRight: value }),
* my: (value) => ({ marginTop: value, marginBottom: value }),
* // Padding shortcuts
* px: (value) => ({ paddingLeft: value, paddingRight: value }),
* py: (value) => ({ paddingTop: value, paddingBottom: value }),
* // Size shortcut
* size: (value) => ({ width: value, height: value }),
* },
* });
*
* // Use utils in your styles!
* const buttonStyles = styled((ctx, t) => ctx({
* slots: ["root"],
* base: {
* root: {
* backgroundColor: t.colors.primary,
* px: 16, // → paddingLeft: 16, paddingRight: 16
* py: 12, // → paddingTop: 12, paddingBottom: 12
* },
* },
* }));
* ```
*/
export declare function createNVA<D extends Record<string, string>, K extends Record<string, string> = D, U extends UtilsConfig = {}>(options?: {
theme?: CreateNVATheme<D, K>;
utils?: U;
}): {
/**
* The resolved theme object with flattened colors.
* Colors use the default (light) scheme.
* Use ThemeProvider to access dark mode colors.
*/
theme: {
/**
* Colors: User-defined semantic colors merged with Tailwind palette.
* User colors override Tailwind colors if keys conflict.
*/
colors: typeof tailwindColors & D;
/** Spacing scale (0, px, 0.5, 1, 2, 4, 8, etc.) */
spacing: typeof tailwindSpacing;
/** Font size scale (xs, sm, base, lg, xl, 2xl, etc.) */
fontSizes: typeof tailwindFontSizes;
/** Border radius scale (none, sm, md, lg, xl, full, etc.) */
radii: typeof tailwindRadii;
/** Shadow definitions for iOS and Android */
shadows: typeof tailwindShadows;
/** Z-index scale (0, 10, 20, 30, 40, 50) */
zIndex: typeof tailwindZIndex;
/** Opacity scale (0, 5, 10, ..., 95, 100) */
opacity: typeof tailwindOpacity;
/** Line height scale (3, 4, ..., 10, none, tight, normal, etc.) */
lineHeights: typeof tailwindLineHeights;
/** Font weight scale (thin, light, normal, medium, bold, etc.) */
fontWeights: typeof tailwindFontWeights;
/** Letter spacing scale (tighter, tight, normal, wide, wider, widest) */
letterSpacing: typeof tailwindLetterSpacing;
/** Border width scale (0, DEFAULT, 2, 4, 8) */
borderWidths: typeof tailwindBorderWidths;
/** Animation duration scale (0, 75, 100, 150, 200, 300, 500, 700, 1000) */
durations: typeof tailwindDurations;
};
/**
* The color scheme configuration with both default and dark colors.
* Pass this to ThemeProvider for dark mode support.
*/
colorScheme: ColorSchemeConfig<D> | undefined;
/**
* Creates styled components with variant support and theme access.
* Utils defined in createNVA are automatically expanded in styles.
*/
styled: {
<const S extends string, const V extends VariantsWithUtils<S, U>>(config: ConfigWithUtils<S, V, U>): (props?: DefaultVariantsWithUtils<S, V, U>) => Base<S>;
<const S extends string, const V extends VariantsWithUtils<S, U>>(configFactory: (defineConfig: <const S_1 extends string, const V_1 extends VariantsWithUtils<S_1, U>>(config: ConfigWithUtils<S_1, V_1, U>) => ConfigWithUtils<S_1, V_1, U>, theme: {
/**
* Colors: User-defined semantic colors merged with Tailwind palette.
* User colors override Tailwind colors if keys conflict.
*/
colors: typeof tailwindColors & D;
/** Spacing scale (0, px, 0.5, 1, 2, 4, 8, etc.) */
spacing: typeof tailwindSpacing;
/** Font size scale (xs, sm, base, lg, xl, 2xl, etc.) */
fontSizes: typeof tailwindFontSizes;
/** Border radius scale (none, sm, md, lg, xl, full, etc.) */
radii: typeof tailwindRadii;
/** Shadow definitions for iOS and Android */
shadows: typeof tailwindShadows;
/** Z-index scale (0, 10, 20, 30, 40, 50) */
zIndex: typeof tailwindZIndex;
/** Opacity scale (0, 5, 10, ..., 95, 100) */
opacity: typeof tailwindOpacity;
/** Line height scale (3, 4, ..., 10, none, tight, normal, etc.) */
lineHeights: typeof tailwindLineHeights;
/** Font weight scale (thin, light, normal, medium, bold, etc.) */
fontWeights: typeof tailwindFontWeights;
/** Letter spacing scale (tighter, tight, normal, wide, wider, widest) */
letterSpacing: typeof tailwindLetterSpacing;
/** Border width scale (0, DEFAULT, 2, 4, 8) */
borderWidths: typeof tailwindBorderWidths;
/** Animation duration scale (0, 75, 100, 150, 200, 300, 500, 700, 1000) */
durations: typeof tailwindDurations;
}) => ConfigWithUtils<S, V, U>): (props?: DefaultVariantsWithUtils<S, V, U>) => Base<S>;
};
/**
* The utils configuration for use outside of styled.
* Useful for applying utils to inline styles.
*/
utils: U;
};
/**
* Clears all style caches. Useful for testing or hot reloading scenarios.
* Note: This only clears the primitive cache. WeakMap entries are
* automatically garbage collected when their keys are no longer referenced.
*/
export declare function clearStyleCache(): void;
export {};