xp.js-styled
Version:
Build performant styled components for Web, iOS and Android platforms.
323 lines (322 loc) • 11.1 kB
TypeScript
import { DimensionValue, FlatList, ImageStyle, Pressable, ScrollView, TextProps, TextStyle, View, ViewStyle } from "react-native";
import { KeysOfUnion } from "type-fest";
import { Breakpoints, ColorPallete, FontWeights } from "./constants";
/**
* Type representing a color in RGB format.
* Example: rgb(255, 255, 255)
*/
type RGBColor = `rgb(${number}, ${number}, ${number})` | `rgb(${number},${number},${number})`;
/**
* Type representing a color in RGBA format.
* Example: rgba(255, 255, 255, 0.5)
*/
type RGBAColor = `rgba(${number}, ${number}, ${number}, ${number})` | `rgba(${number},${number},${number},${number})`;
/**
* Type representing a color in HEX format.
* Example: #FFFFFF
*/
type HEXColor = `#${string}`;
/**
* Type representing a color in HSL format.
* Example: hsl(0, 100%, 50%)
*/
type HSLColor = `hsl(${number}, ${number}, ${number})`;
/**
* Type representing a color in HSLA format.
* Example: hsla(0, 100%, 50%, 0.5)
*/
type HSLAColor = `hsla(${number}, ${number}, ${number}, ${number})`;
/**
* Type representing a color range.
*/
type ColorRange = 100 | 150 | 200 | 250 | 300 | 350 | 400 | 450 | 500 | 550 | 600 | 650 | 700 | 750 | 800 | 850 | 900;
/**
* Type representing a declarative color.
* Can be in RGB, RGBA, HEX, HSL, or HSLA format,
* or reference a color from a predefined palette.
*/
type DeclarativeColor = `${ColorPalleteKey}.${ColorRange}` | `${ColorPalleteKey}`;
/**
* Union type representing various types of colors.
*/
export type TypedColor = RGBColor | RGBAColor | HEXColor | HSLColor | HSLAColor | DeclarativeColor;
/**
* Type defining all the optional media queries you can apply to a given component.
*/
export type WithMediaQuery<T = any> = T & {
"@ios"?: T & WithMediaQuery<T>;
"@android"?: T & WithMediaQuery<T>;
"@windows"?: T & WithMediaQuery<T>;
"@macos"?: T & WithMediaQuery<T>;
"@web"?: T & WithMediaQuery<T>;
"@light"?: T & WithMediaQuery<T>;
"@dark"?: T & WithMediaQuery<T>;
} & {
[key in `@${BreakpointsKey}`]?: T & WithMediaQuery<T>;
};
/**
* Type representing styles with typed properties for common attributes.
*/
export type Style<TFields = ViewStyle> = PatchProps<TFields>;
/**
* Typography properties type.
*/
export type TypographyProps = {
fontSize?: TypedDimension;
fontWeight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | FontWeightKey;
};
/**
* Spacing properties type.
*/
export type SpacingProps = {
padding?: TypedDimension;
paddingVertical?: TypedDimension;
paddingHorizontal?: TypedDimension;
paddingTop?: TypedDimension;
paddingBottom?: TypedDimension;
paddingLeft?: TypedDimension;
paddingRight?: TypedDimension;
marginVertical?: TypedDimension;
marginHorizontal?: TypedDimension;
margin?: TypedDimension;
marginTop?: TypedDimension;
marginBottom?: TypedDimension;
marginLeft?: TypedDimension;
marginRight?: TypedDimension;
gap?: TypedDimension;
rowGap?: TypedDimension;
columnGap?: TypedDimension;
};
/**
* Layout properties type.
*/
export type LayoutProps = {
flex?: number;
size?: TypedDimension;
width?: TypedDimension;
height?: TypedDimension;
minWidth?: TypedDimension;
minHeight?: TypedDimension;
maxWidth?: TypedDimension;
maxHeight?: TypedDimension;
};
/**
* Shortcut properties type.
*/
export type ShortcutProps = {
f?: TypedDimension;
s?: TypedDimension;
w?: TypedDimension;
h?: TypedDimension;
minW?: TypedDimension;
minH?: TypedDimension;
maxW?: TypedDimension;
maxH?: TypedDimension;
bW?: TypedDimension;
bRadius?: TypedDimension;
bColor?: TypedColor;
p?: TypedDimension;
pX?: TypedDimension;
pY?: TypedDimension;
pT?: TypedDimension;
pL?: TypedDimension;
pB?: TypedDimension;
pR?: TypedDimension;
m?: TypedDimension;
mX?: TypedDimension;
mY?: TypedDimension;
mT?: TypedDimension;
mL?: TypedDimension;
mB?: TypedDimension;
mR?: TypedDimension;
bgColor?: TypedColor;
font?: string;
g?: TypedDimension;
t?: TypedDimension;
b?: TypedDimension;
r?: TypedDimension;
l?: TypedDimension;
z?: ViewStyle["zIndex"];
align?: ViewStyle["alignItems"];
justify?: ViewStyle["justifyContent"];
grow?: ViewStyle["flexGrow"];
shrink?: ViewStyle["flexShrink"];
wrap?: ViewStyle["flexWrap"];
lines?: TextProps["numberOfLines"];
spacing?: TextStyle["letterSpacing"];
center?: boolean;
};
/**
* Border properties type.
*/
export type BorderProps = {
borderRadius?: TypedDimension;
borderBottomLeftRadius?: TypedDimension;
borderBottomRightRadius?: TypedDimension;
borderBottomStartRadius?: TypedDimension;
borderBottomEndRadius?: TypedDimension;
borderTopLeftRadius?: TypedDimension;
borderTopRightRadius?: TypedDimension;
borderTopStartRadius?: TypedDimension;
borderTopEndRadius?: TypedDimension;
};
/**
* Color properties type.
*/
export type ColorProps = {
color?: TypedColor;
shadowColor?: TypedColor;
backgroundColor?: TypedColor;
} & {
[key in `${string}Color`]?: TypedColor;
};
/**
* Patch a type prop if present.
*/
export type PatchType<TBase, TOverride> = {
[K in keyof TBase]: K extends keyof TOverride ? TOverride[K] : TBase[K];
};
/**
* All properties type.
*/
export type PatchProps<TProps = {}> = PatchType<TProps, TypographyProps & SpacingProps & ColorProps & BorderProps> & LayoutProps & ShortcutProps;
/**
* Type representing a dimension.
*/
export type TypedDimension = `${number}px` | DimensionValue | BreakpointsKey | `${"2xxl" | "3xxl" | "4xxl" | "5xxl" | "6xxl" | "7xxl" | "8xxl" | "9xxl"}`;
/**
* Schema defining stylesheets with optional media queries.
*/
export type Stylesheets = Partial<{
[key: string]: WithMediaQuery<Style>;
}>;
/**
* Schema defining color palettes for light and dark modes, along with platform-specific colors.
*/
export type Colors = {
"@light"?: {
[key: string]: TypedColor;
};
"@dark"?: {
[key: string]: TypedColor;
};
} & {
[key: string]: TypedColor;
};
/**
* Responsive schema for defining layout at diferent breakpoints.
*/
export type Responsive<T = any> = {
[key in BreakpointsKey]: T;
};
/**
* Schema combining color palettes, stylesheets, sizes, font sizes, and breakpoints to form a complete theme.
*/
export type Theme = {
colors?: Colors;
styles?: Stylesheets;
spacing?: Responsive<number | undefined>;
fontWeights?: Responsive<number | undefined>;
fontSizes?: Responsive<number | undefined>;
breakpoints?: Responsive<number | undefined>;
};
/**
* Union type representing the keys of the font weight.
*/
export type FontWeightKey = keyof typeof FontWeights;
/**
* Union type representing the keys of the color palette.
*/
export type ColorPalleteKey = keyof typeof ColorPallete;
/**
* Union type representing the keys of the default sizes.
*/
export type BreakpointsKey = KeysOfUnion<typeof Breakpoints>;
/**
* Type representing styled components with support for theming, and variants.
*/
export type StyledStyle<TStyleProps = ViewStyle, TVariantNames extends string = never> = {
parentStyles?: string[];
variants?: Record<TVariantNames, Partial<WithMediaQuery<Style<TStyleProps>>>>;
} & WithMediaQuery<Style<TStyleProps>> & object;
/**
* Type to remove keys from type definitions.
*/
export type OmitKeys<T, TOmit> = Omit<T, keyof TOmit>;
/**
* Type representing props for styled components, combining component-specific, style-specific,
* and variant-specific properties.
*
* @template TProps - Component-specific properties.
* @template TStyleProps - Style-specific properties.
* @template TVariants - Variant-specific properties.
* @template ThemeType - Theme-specific properties.
*/
export type StyledProps<TProps, TStyleProps, TVariants> = {
/** Optional variant property for component styling. */
variant?: TVariants;
/** Children nodes to be rendered within the component. */
children?: React.ReactNode;
/** Style properties including possible overrides. */
style?: WithMediaQuery<PatchProps<TStyleProps>>;
} & WithMediaQuery<PatchProps<TProps & TStyleProps>>;
/**
* Type representing parameters for a transformation function.
*
* @template TContext - Context type used during transformation.
*/
export type TransformParams<TContext = {}> = {
/** The value to be transformed. */
value: any;
/** The key associated with the value. */
key: string;
/** Optional context data for transformation. */
ctx?: TContext;
};
/**
* Type defining the properties required by the deepTransform function.
*
* @template TCollection - The type of the input object to be transformed.
* @template TContext - Context type used during transformation, which includes a readonly 'deep' property.
*/
export type DeepMapProps<TCollection extends object = {}, TContext extends object & {
deep: Readonly<number>;
} = {
deep: number;
}> = {
/** The input object to be transformed. */
values: TCollection;
/** Function to determine if a value should be transformed. */
match: (props: TransformParams<TContext>) => boolean;
/** Function to transform individual values within the input object. */
map: (props: TransformParams<TContext>) => any;
/** Function to handle nested objects within the input object. */
onNesting?: (props: Omit<TransformParams<TContext> & {
values: TCollection;
}, "value">) => TContext;
/** Optional initial context data for transformation. */
initialContext?: TContext;
/** Optional keys to skip during transformation. */
skipKeys?: string[];
};
/**
* Extracts the properties of a React component type.
* @template T - The React component type.
* @typedef {T extends React.ComponentType<infer P> ? P : never} ExtractComponentProps
*/
export type ExtractComponentProps<T> = T extends React.ComponentType<infer P> ? P : never;
/**
* Extracts the style properties from an object with a style property.
* @template T - The object type.
* @typedef {T extends { style: infer S } ? S : never} ExtractStyleProps
*/
export type ExtractStyleProps<T> = T extends {
style: infer S;
} ? S : never;
/**
* Maps a React component type to its corresponding style properties.
*/
export type ComponentStyleProps<T> = ShortcutProps & T extends typeof View ? ViewStyle : T extends typeof Pressable ? ViewStyle : T extends typeof Text ? TextStyle : T extends typeof Image ? ImageStyle : T extends typeof ScrollView ? ViewStyle : T extends typeof FlatList ? ViewStyle : T extends React.ComponentType<infer P> ? P extends {
style?: infer S;
} ? S : {} : {};
export {};