Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
16 kB · 816 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817/** * Theme atoms - Enhanced exports with pairify function for array-style syntax * These provide direct access to static design tokens and support composition */
import { Platform } from "react-native";import { animations, borderRadius, colors as rawColors, scrims, shadows, spacing, touchTargets, typography,} from "./tokens";
// Type for style objects that can be spreadtype StyleValue = Record<string, any>;
/** * Pairify function - converts nested objects into key-value pairs that return style objects * This allows for array-style syntax like style={[a.borders.green[300], a.shadows.xl]} */function pairify<T extends Record<string, any>>( obj: T, styleKeyPrefix: string,): Record<keyof T, StyleValue> { const result: Record<string, StyleValue> = {};
for (const [key, value] of Object.entries(obj)) { if (typeof value === "object" && value !== null && !Array.isArray(value)) { // For nested objects (like color scales), create another level result[key] = {}; for (const [nestedKey, nestedValue] of Object.entries(value)) { result[key][nestedKey] = { [styleKeyPrefix]: nestedValue }; } } else { // For simple values, create the style object directly result[key] = { [styleKeyPrefix]: value }; } }
return result as Record<keyof T, StyleValue>;}
/** * Create pairified style atoms for easy composition */
// Re-export static design tokens that don't change with themeexport { animations, borderRadius, shadows, spacing, touchTargets };
// Export raw color tokens for advanced use casesexport const colors = rawColors;
// Platform-aware typography helperexport const getPlatformTypography = () => { if (Platform.OS === "ios") { return typography.ios; } else if (Platform.OS === "android") { return typography.android; } return typography.universal;};
// Export all typography scalesexport const typographyAtoms = { platform: getPlatformTypography(), universal: typography.universal, ios: typography.ios, android: typography.android,};
// Static icon sizes (colors are handled by theme)export const iconSizes = { sm: 16, md: 20, lg: 24, xl: 32,};
// Common layout utilitiesexport const layout = { flex: { center: { justifyContent: "center" as const, alignItems: "center" as const, }, alignCenter: { alignItems: "center" as const, }, justifyCenter: { justifyContent: "center" as const, }, row: { flexDirection: "row" as const, }, column: { flexDirection: "column" as const, }, spaceBetween: { justifyContent: "space-between" as const, }, spaceAround: { justifyContent: "space-around" as const, }, spaceEvenly: { justifyContent: "space-evenly" as const, }, direction: pairify( { row: "row", column: "column", "row-reverse": "row-reverse", "column-reverse": "column-reverse", }, "flexDirection", ), justify: pairify( { start: "flex-start", end: "flex-end", center: "center", between: "space-between", around: "space-around", evenly: "space-evenly", }, "justifyContent", ), align: pairify( { start: "flex-start", end: "flex-end", center: "center", stretch: "stretch", baseline: "baseline", }, "alignItems", ), wrap: pairify( { wrap: "wrap", nowrap: "nowrap", reverse: "wrap-reverse", }, "flexWrap", ), }, position: pairify( { absolute: "absolute", relative: "relative", static: "static", }, "position", ),};
// Enhanced border utilities with pairified colors and widthsexport const borders = { width: pairify( { thin: 1, medium: 2, thick: 4, }, "borderWidth", ),
style: pairify( { solid: "solid", dashed: "dashed", dotted: "dotted", }, "borderStyle", ),
// Pairified color borders color: pairify(rawColors, "borderColor"),
// Top border utilities top: { width: pairify( { thin: 1, medium: 2, thick: 4, }, "borderTopWidth", ), color: pairify(rawColors, "borderTopColor"), },
// Bottom border utilities bottom: { width: pairify( { thin: 1, medium: 2, thick: 4, }, "borderBottomWidth", ), color: pairify(rawColors, "borderBottomColor"), },
// Left border utilities left: { width: pairify( { thin: 1, medium: 2, thick: 4, }, "borderLeftWidth", ), color: pairify(rawColors, "borderLeftColor"), },
// Right border utilities right: { width: pairify( { thin: 1, medium: 2, thick: 4, }, "borderRightWidth", ), color: pairify(rawColors, "borderRightColor"), },};
// Pairified spacing utilitiesexport const spacingAtoms = { margin: pairify(spacing, "margin"), marginTop: pairify(spacing, "marginTop"), marginRight: pairify(spacing, "marginRight"), marginBottom: pairify(spacing, "marginBottom"), marginLeft: pairify(spacing, "marginLeft"), marginHorizontal: pairify(spacing, "marginHorizontal"), marginVertical: pairify(spacing, "marginVertical"),
padding: pairify(spacing, "padding"), paddingTop: pairify(spacing, "paddingTop"), paddingRight: pairify(spacing, "paddingRight"), paddingBottom: pairify(spacing, "paddingBottom"), paddingLeft: pairify(spacing, "paddingLeft"), paddingHorizontal: pairify(spacing, "paddingHorizontal"), paddingVertical: pairify(spacing, "paddingVertical"),};
// Pairified border radius utilitiesexport const radiusAtoms = { all: pairify(borderRadius, "borderRadius"), top: pairify(borderRadius, "borderTopLeftRadius"), topRight: pairify(borderRadius, "borderTopRightRadius"), bottom: pairify(borderRadius, "borderBottomLeftRadius"), bottomRight: pairify(borderRadius, "borderBottomRightRadius"), left: pairify(borderRadius, "borderTopLeftRadius"), right: pairify(borderRadius, "borderTopRightRadius"),};
// Background color utilitiesexport const backgrounds = pairify(rawColors, "backgroundColor");
// Text color utilitiesexport const textColors = pairify(rawColors, "color");
// Percentage-based sizesconst percentageSizes = { "10": "10%", "20": "20%", "25": "25%", "30": "30%", "33": "33.333333%", "40": "40%", "50": "50%", "60": "60%", "66": "66.666667%", "70": "70%", "75": "75%", "80": "80%", "90": "90%", "100": "100%",} as const;
// Size utilities (width and height)export const sizes = { width: { ...pairify(spacing, "width"), percent: pairify(percentageSizes, "width"), }, height: { ...pairify(spacing, "height"), percent: pairify(percentageSizes, "height"), }, minWidth: { ...pairify(spacing, "minWidth"), percent: pairify(percentageSizes, "minWidth"), }, minHeight: { ...pairify(spacing, "minHeight"), percent: pairify(percentageSizes, "minHeight"), }, maxWidth: { ...pairify(spacing, "maxWidth"), percent: pairify(percentageSizes, "maxWidth"), }, maxHeight: { ...pairify(spacing, "maxHeight"), percent: pairify(percentageSizes, "maxHeight"), },};
// Flex utilitiesexport const flex = { values: pairify( { 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, }, "flex", ),
grow: pairify( { 0: 0, 1: 1, }, "flexGrow", ),
shrink: pairify( { 0: 0, 1: 1, }, "flexShrink", ),
basis: { ...pairify(spacing, "flexBasis"), ...pairify(percentageSizes, "flexBasis"), auto: { flexBasis: "auto" }, },};
// Opacity utilitiesexport const opacity = pairify( { 0: 0, 5: 0.05, 10: 0.1, 20: 0.2, 25: 0.25, 30: 0.3, 40: 0.4, 50: 0.5, 60: 0.6, 70: 0.7, 75: 0.75, 80: 0.8, 90: 0.9, 95: 0.95, 100: 1, }, "opacity",);
// Z-index utilitiesexport const zIndex = pairify( { 0: 0, 10: 10, 20: 20, 30: 30, 40: 40, 50: 50, auto: "auto", }, "zIndex",);
// Overflow utilitiesexport const overflow = pairify( { visible: "visible", hidden: "hidden", scroll: "scroll", }, "overflow",);
// Text alignment utilitiesexport const textAlign = pairify( { left: "left", center: "center", right: "right", justify: "justify", auto: "auto", }, "textAlign",);
// Font weight utilitiesexport const fontWeight = pairify( { thin: "100", extralight: "200", light: "300", normal: "400", medium: "500", semibold: "600", bold: "700", extrabold: "800", black: "900", }, "fontWeight",);
// Font size utilities (separate from typography for quick access)export const fontSize = pairify( { xs: 12, sm: 14, base: 16, lg: 18, xl: 20, "2xl": 24, "3xl": 30, "4xl": 36, "5xl": 48, "6xl": 60, "7xl": 72, "8xl": 96, "9xl": 128, }, "fontSize",);
// Line height utilitiesexport const lineHeight = pairify( { none: 1, tight: 1.25, snug: 1.375, normal: 1.5, relaxed: 1.625, loose: 2, 3: 12, 4: 16, 5: 20, 6: 24, 7: 28, 8: 32, 9: 36, 10: 40, }, "lineHeight",);
// Letter spacing utilitiesexport const letterSpacing = pairify( { tighter: -0.5, tight: -0.25, normal: 0, wide: 0.25, wider: 0.5, widest: 1, }, "letterSpacing",);
// Text transform utilitiesexport const textTransform = pairify( { uppercase: "uppercase", lowercase: "lowercase", capitalize: "capitalize", none: "none", }, "textTransform",);
// Text decoration utilitiesexport const textDecoration = pairify( { none: "none", underline: "underline", lineThrough: "line-through", underlineLineThrough: "underline line-through", }, "textDecorationLine",);
// Text align vertical utilities (React Native specific)export const textAlignVertical = pairify( { auto: "auto", top: "top", bottom: "bottom", center: "center", }, "textAlignVertical",);
// Transform utilitiesexport const transforms = { rotate: pairify( { 0: 0, 1: 1, 2: 2, 3: 3, 6: 6, 12: 12, 45: 45, 90: 90, 180: 180, 270: 270, }, "rotate", ),
scale: pairify( { 0: 0, 50: 0.5, 75: 0.75, 90: 0.9, 95: 0.95, 100: 1, 105: 1.05, 110: 1.1, 125: 1.25, 150: 1.5, 200: 2, }, "scale", ),
scaleX: pairify( { 0: 0, 50: 0.5, 75: 0.75, 90: 0.9, 95: 0.95, 100: 1, 105: 1.05, 110: 1.1, 125: 1.25, 150: 1.5, 200: 2, }, "scaleX", ),
scaleY: pairify( { 0: 0, 50: 0.5, 75: 0.75, 90: 0.9, 95: 0.95, 100: 1, 105: 1.05, 110: 1.1, 125: 1.25, 150: 1.5, 200: 2, }, "scaleY", ),
translateX: pairify(spacing, "translateX"), translateY: pairify(spacing, "translateY"),};
// Absolute positioning utilitiesexport const position = { top: pairify(spacing, "top"), right: pairify(spacing, "right"), bottom: pairify(spacing, "bottom"), left: pairify(spacing, "left"),
// Common position combinations topLeft: (top: number, left: number) => ({ position: "absolute" as const, top, left, }), topRight: (top: number, right: number) => ({ position: "absolute" as const, top, right, }), bottomLeft: (bottom: number, left: number) => ({ position: "absolute" as const, bottom, left, }), bottomRight: (bottom: number, right: number) => ({ position: "absolute" as const, bottom, right, }),
// Percentage-based positioning percent: { top: pairify( { 0: "0%", 25: "25%", 50: "50%", 75: "75%", 100: "100%", }, "top", ), right: pairify( { 0: "0%", 25: "25%", 50: "50%", 75: "75%", 100: "100%", }, "right", ), bottom: pairify( { 0: "0%", 25: "25%", 50: "50%", 75: "75%", 100: "100%", }, "bottom", ), left: pairify( { 0: "0%", 25: "25%", 50: "50%", 75: "75%", 100: "100%", }, "left", ), },};
// Aspect ratio utilities (React Native 0.71+)export const aspectRatio = pairify( { square: 1, video: 16 / 9, photo: 4 / 3, portrait: 3 / 4, wide: 21 / 9, ultrawide: 32 / 9, "1/1": 1, "3/2": 3 / 2, "4/3": 4 / 3, "16/9": 16 / 9, "21/9": 21 / 9, }, "aspectRatio",);
// Gap utilities (React Native 0.71+)export const gap = { row: pairify(spacing, "rowGap"), column: pairify(spacing, "columnGap"), all: pairify(spacing, "gap"),};
// Common layout patternsexport const layouts = { // Full screen fullScreen: { position: "absolute" as const, top: 0, left: 0, right: 0, bottom: 0, },
// Centered content centered: { flex: 1, justifyContent: "center" as const, alignItems: "center" as const, },
// Centered modal/overlay (scrim color: prefer theme.colors.overlay so the // scrim adapts to the color scheme) overlay: { position: "absolute" as const, top: 0, left: 0, right: 0, bottom: 0, justifyContent: "center" as const, alignItems: "center" as const, backgroundColor: scrims.dark, },
// Safe area friendly safeContainer: { flex: 1, paddingTop: Platform.OS === "ios" ? 44 : 0, // Status bar height },
// Row with space between spaceBetweenRow: { flexDirection: "row" as const, justifyContent: "space-between" as const, alignItems: "center" as const, },
// Sticky header stickyHeader: { position: "absolute" as const, top: 0, left: 0, right: 0, zIndex: 10, },
// Bottom sheet style bottomSheet: { position: "absolute" as const, bottom: 0, left: 0, right: 0, borderTopLeftRadius: 16, borderTopRightRadius: 16, },};
// Export everything as a combined atoms object for convenienceexport const atoms = { colors: rawColors, spacing, borderRadius, radius: radiusAtoms, typography: typographyAtoms, shadows, touchTargets, animations, iconSizes, layout, borders, backgrounds, textColors, spacingAtoms, sizes, flex, opacity, zIndex, overflow, textAlign, fontWeight, fontSize, lineHeight, letterSpacing, textTransform, textDecoration, textAlignVertical, transforms, position, aspectRatio, gap, layouts,};
// Convenient shorthand aliasesexport const a = atoms;export const bg = backgrounds;export const text = textColors;export const m = spacingAtoms.margin;export const mt = spacingAtoms.marginTop;export const mr = spacingAtoms.marginRight;export const mb = spacingAtoms.marginBottom;export const ml = spacingAtoms.marginLeft;export const mx = spacingAtoms.marginHorizontal;export const my = spacingAtoms.marginVertical;export const p = spacingAtoms.padding;export const pt = spacingAtoms.paddingTop;export const pr = spacingAtoms.paddingRight;export const pb = spacingAtoms.paddingBottom;export const pl = spacingAtoms.paddingLeft;export const px = spacingAtoms.paddingHorizontal;export const py = spacingAtoms.paddingVertical;export const w = sizes.width;export const h = sizes.height;export const r = radiusAtoms.all;export const top = position.top;export const right = position.right;export const bottom = position.bottom;export const left = position.left;export const rotate = transforms.rotate;export const scale = transforms.scale;export const translateX = transforms.translateX;export const translateY = transforms.translateY;