UNPKG

august-design-system

Version:

A comprehensive React Native design system following Apple Human Interface Guidelines

1,438 lines (1,425 loc) 31.2 kB
'use strict'; var React = require('react'); var reactNative = require('react-native'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var React__default = /*#__PURE__*/_interopDefault(React); // src/design-system/tokens/colors.ts var palette = { // Gray scale - iOS system grays gray: { 50: "#F2F2F7", 100: "#E5E5EA", 200: "#D1D1D6", 300: "#C7C7CC", 400: "#AEAEB2", 500: "#8E8E93", 600: "#636366", 700: "#48484A", 800: "#3A3A3C", 900: "#2C2C2E", 950: "#1C1C1E" }, // System colors - iOS standard palette // Light mode values red: { light: "#FF3B30", dark: "#FF453A" }, orange: { light: "#FF9500", dark: "#FF9F0A" }, yellow: { light: "#FFCC00", dark: "#FFD60A" }, green: { light: "#34C759", dark: "#30D158" }, mint: { light: "#00C7BE", dark: "#63E6E2" }, teal: { light: "#30B0C7", dark: "#40C8E0" }, cyan: { light: "#32ADE6", dark: "#64D2FF" }, blue: { light: "#007AFF", dark: "#0A84FF" }, indigo: { light: "#5856D6", dark: "#5E5CE6" }, purple: { light: "#AF52DE", dark: "#BF5AF2" }, pink: { light: "#FF2D55", dark: "#FF375F" }, brown: { light: "#A2845E", dark: "#AC8E68" } }; var lightColors = { // Background colors - iOS grouped table view style layering background: { primary: "#FFFFFF", secondary: "#F2F2F7", tertiary: "#FFFFFF", grouped: "#F2F2F7", groupedSecondary: "#FFFFFF", groupedTertiary: "#F2F2F7" }, // Label colors - for text content label: { primary: "#000000", // 100% black secondary: "rgba(60, 60, 67, 0.6)", // 60% opacity tertiary: "rgba(60, 60, 67, 0.3)", // 30% opacity quaternary: "rgba(60, 60, 67, 0.18)" // 18% opacity }, // Fill colors - for thin and small shapes fill: { primary: "rgba(120, 120, 128, 0.2)", secondary: "rgba(120, 120, 128, 0.16)", tertiary: "rgba(118, 118, 128, 0.12)", quaternary: "rgba(116, 116, 128, 0.08)" }, // Separator colors separator: { opaque: "#C6C6C8", nonOpaque: "rgba(60, 60, 67, 0.36)" }, // System colors - Apple standard system: { red: palette.red.light, orange: palette.orange.light, yellow: palette.yellow.light, green: palette.green.light, mint: palette.mint.light, teal: palette.teal.light, cyan: palette.cyan.light, blue: palette.blue.light, indigo: palette.indigo.light, purple: palette.purple.light, pink: palette.pink.light, brown: palette.brown.light, gray: palette.gray[500], gray2: palette.gray[400], gray3: palette.gray[300], gray4: palette.gray[200], gray5: palette.gray[100], gray6: palette.gray[50] }, // Semantic colors - functional meaning semantic: { success: palette.green.light, warning: palette.orange.light, error: palette.red.light, info: palette.blue.light }, // Interactive colors interactive: { tint: palette.blue.light, tintPressed: "#0062CC", // Darkened blue for pressed state tintDisabled: "rgba(0, 122, 255, 0.3)", destructive: palette.red.light, destructivePressed: "#CC2F26" }, // Material/Blur backgrounds - approximated for non-blur fallback material: { thin: "rgba(255, 255, 255, 0.6)", regular: "rgba(255, 255, 255, 0.72)", thick: "rgba(255, 255, 255, 0.85)", chrome: "rgba(247, 247, 247, 0.8)" } }; var darkColors = { // Background colors - elevated surfaces in dark mode background: { primary: "#000000", secondary: "#1C1C1E", tertiary: "#2C2C2E", grouped: "#000000", groupedSecondary: "#1C1C1E", groupedTertiary: "#2C2C2E" }, // Label colors - inverted for dark mode label: { primary: "#FFFFFF", secondary: "rgba(235, 235, 245, 0.6)", tertiary: "rgba(235, 235, 245, 0.3)", quaternary: "rgba(235, 235, 245, 0.18)" }, // Fill colors - adjusted for dark backgrounds fill: { primary: "rgba(120, 120, 128, 0.36)", secondary: "rgba(120, 120, 128, 0.32)", tertiary: "rgba(118, 118, 128, 0.24)", quaternary: "rgba(116, 116, 128, 0.18)" }, // Separator colors separator: { opaque: "#38383A", nonOpaque: "rgba(84, 84, 88, 0.6)" }, // System colors - adjusted for dark mode (higher luminance) system: { red: palette.red.dark, orange: palette.orange.dark, yellow: palette.yellow.dark, green: palette.green.dark, mint: palette.mint.dark, teal: palette.teal.dark, cyan: palette.cyan.dark, blue: palette.blue.dark, indigo: palette.indigo.dark, purple: palette.purple.dark, pink: palette.pink.dark, brown: palette.brown.dark, gray: palette.gray[500], gray2: palette.gray[600], gray3: palette.gray[700], gray4: palette.gray[800], gray5: palette.gray[900], gray6: palette.gray[950] }, // Semantic colors - dark mode variants semantic: { success: palette.green.dark, warning: palette.orange.dark, error: palette.red.dark, info: palette.blue.dark }, // Interactive colors - adjusted for dark backgrounds interactive: { tint: palette.blue.dark, tintPressed: "#409CFF", // Lightened blue for pressed state in dark mode tintDisabled: "rgba(10, 132, 255, 0.3)", destructive: palette.red.dark, destructivePressed: "#FF6961" }, // Material/Blur backgrounds - dark mode variants material: { thin: "rgba(30, 30, 30, 0.6)", regular: "rgba(30, 30, 30, 0.72)", thick: "rgba(30, 30, 30, 0.85)", chrome: "rgba(36, 36, 38, 0.8)" } }; // src/design-system/tokens/typography.ts var fontFamily = { regular: "System", medium: "System", semibold: "System", bold: "System", heavy: "System", monospace: "Menlo", // Falls back to platform monospace rounded: "System" // SF Pro Rounded on iOS }; var typography = { // ========================================================================== // DISPLAY STYLES // Large, prominent text for titles and headers // ========================================================================== /** * Large Title - Used for main screen titles in navigation bars. * iOS: 34pt Regular */ largeTitle: { fontFamily: fontFamily.regular, fontSize: 34, lineHeight: 41, // 1.2x letterSpacing: 0.37, fontWeight: "400" }, /** * Title 1 - Primary content titles. * iOS: 28pt Regular */ title1: { fontFamily: fontFamily.regular, fontSize: 28, lineHeight: 34, // 1.21x letterSpacing: 0.36, fontWeight: "400" }, /** * Title 2 - Secondary titles. * iOS: 22pt Regular */ title2: { fontFamily: fontFamily.regular, fontSize: 22, lineHeight: 28, // 1.27x letterSpacing: 0.35, fontWeight: "400" }, /** * Title 3 - Tertiary titles. * iOS: 20pt Regular */ title3: { fontFamily: fontFamily.regular, fontSize: 20, lineHeight: 25, // 1.25x letterSpacing: 0.38, fontWeight: "400" }, // ========================================================================== // HEADLINE STYLES // For section headers and emphasized text // ========================================================================== /** * Headline - Section headers, emphasized body text. * iOS: 17pt Semibold */ headline: { fontFamily: fontFamily.semibold, fontSize: 17, lineHeight: 22, // 1.29x letterSpacing: -0.41, fontWeight: "600" }, /** * Subheadline - Subordinate section headers. * iOS: 15pt Regular */ subheadline: { fontFamily: fontFamily.regular, fontSize: 15, lineHeight: 20, // 1.33x letterSpacing: -0.24, fontWeight: "400" }, // ========================================================================== // BODY STYLES // Primary reading text // ========================================================================== /** * Body - Primary reading text throughout the app. * iOS: 17pt Regular */ body: { fontFamily: fontFamily.regular, fontSize: 17, lineHeight: 22, // 1.29x letterSpacing: -0.41, fontWeight: "400" }, /** * Callout - Secondary text that's slightly smaller than body. * iOS: 16pt Regular */ callout: { fontFamily: fontFamily.regular, fontSize: 16, lineHeight: 21, // 1.31x letterSpacing: -0.32, fontWeight: "400" }, // ========================================================================== // SUPPORTING STYLES // Smaller text for captions, footnotes, and labels // ========================================================================== /** * Footnote - Smaller supporting text. * iOS: 13pt Regular */ footnote: { fontFamily: fontFamily.regular, fontSize: 13, lineHeight: 18, // 1.38x letterSpacing: -0.08, fontWeight: "400" }, /** * Caption 1 - Primary caption style. * iOS: 12pt Regular */ caption1: { fontFamily: fontFamily.regular, fontSize: 12, lineHeight: 16, // 1.33x letterSpacing: 0, fontWeight: "400" }, /** * Caption 2 - Secondary caption style (smallest). * iOS: 11pt Regular */ caption2: { fontFamily: fontFamily.regular, fontSize: 11, lineHeight: 13, // 1.18x letterSpacing: 0.07, fontWeight: "400" } }; function withWeight(style, weight) { return { ...style, fontWeight: weight }; } function emphasized(style) { return withWeight(style, "600"); } ({ bodyEmphasis: emphasized(typography.body), calloutEmphasis: emphasized(typography.callout), footnoteEmphasis: emphasized(typography.footnote), caption1Emphasis: emphasized(typography.caption1), subheadlineEmphasis: emphasized(typography.subheadline) }); // src/design-system/tokens/spacing.ts var spacing = { // Base scale none: 0, xxs: 2, xs: 4, sm: 8, md: 12, lg: 16, xl: 20, xxl: 24, xxxl: 32, xxxxl: 40, xxxxxl: 48, // Semantic spacing - Inset (padding) // Used for content padding inside containers inset: { none: 0, xs: 4, sm: 8, md: 12, lg: 16, // Standard content inset xl: 20 }, // Semantic spacing - Stack (vertical) // Used for vertical spacing between elements stack: { none: 0, xs: 4, sm: 8, // Tight grouping md: 12, lg: 16, // Standard section spacing xl: 24 // Large section spacing }, // Semantic spacing - Inline (horizontal) // Used for horizontal spacing between elements inline: { none: 0, xs: 4, sm: 8, // Icon to text spacing md: 12, lg: 16, // Standard element spacing xl: 24 } }; // src/design-system/tokens/radius.ts var radius = { none: 0, xs: 4, sm: 8, md: 12, lg: 16, xl: 20, xxl: 24, full: 9999 }; ({ /** * Button corner radius (matches iOS default). */ button: radius.sm, /** * Small button corner radius. */ buttonSmall: radius.xs, /** * Card corner radius. */ card: radius.md, /** * Input field corner radius. */ input: radius.sm, /** * Modal/Dialog corner radius. */ modal: radius.lg, /** * Bottom sheet corner radius. */ sheet: radius.xl, /** * Image thumbnail radius. */ thumbnail: radius.sm, /** * Avatar (circular) radius. */ avatar: radius.full, /** * Badge/Chip radius. */ badge: radius.full, /** * Pill button radius. */ pill: radius.full, /** * Tag/Label radius. */ tag: radius.xs, /** * Toast notification radius. */ toast: radius.md, /** * Tooltip radius. */ tooltip: radius.sm, /** * Popover radius. */ popover: radius.md, /** * Search bar radius. */ searchBar: radius.sm, /** * Segment control radius. */ segmentControl: radius.sm, /** * Slider track radius. */ slider: radius.full, /** * Progress bar radius. */ progressBar: radius.full }); // src/design-system/tokens/shadows.ts var shadowColors = { light: "rgba(0, 0, 0, 1)", // Opacity controlled per shadow dark: "rgba(0, 0, 0, 1)" // Deeper shadows in dark mode }; var lightShadows = { /** * No shadow. */ none: { shadowColor: shadowColors.light, shadowOffset: { width: 0, height: 0 }, shadowOpacity: 0, shadowRadius: 0, elevation: 0 }, /** * Extra small shadow - subtle lift. * Use for: Subtle hover states, pressed buttons. */ xs: { shadowColor: shadowColors.light, shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.04, shadowRadius: 2, elevation: 1 }, /** * Small shadow - light elevation. * Use for: Cards, list items, buttons. */ sm: { shadowColor: shadowColors.light, shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.08, shadowRadius: 4, elevation: 2 }, /** * Medium shadow - standard elevation. * Use for: Dropdown menus, popovers, floating action buttons. */ md: { shadowColor: shadowColors.light, shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.12, shadowRadius: 8, elevation: 4 }, /** * Large shadow - prominent elevation. * Use for: Modals, dialogs, navigation overlays. */ lg: { shadowColor: shadowColors.light, shadowOffset: { width: 0, height: 8 }, shadowOpacity: 0.15, shadowRadius: 16, elevation: 8 }, /** * Extra large shadow - high elevation. * Use for: Bottom sheets, side panels. */ xl: { shadowColor: shadowColors.light, shadowOffset: { width: 0, height: 12 }, shadowOpacity: 0.18, shadowRadius: 24, elevation: 12 }, /** * XXL shadow - maximum elevation. * Use for: Full-screen overlays, critical modals. */ xxl: { shadowColor: shadowColors.light, shadowOffset: { width: 0, height: 16 }, shadowOpacity: 0.22, shadowRadius: 32, elevation: 16 } }; var darkShadows = { none: { shadowColor: shadowColors.dark, shadowOffset: { width: 0, height: 0 }, shadowOpacity: 0, shadowRadius: 0, elevation: 0 }, xs: { shadowColor: shadowColors.dark, shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.2, shadowRadius: 2, elevation: 1 }, sm: { shadowColor: shadowColors.dark, shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 4, elevation: 2 }, md: { shadowColor: shadowColors.dark, shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.3, shadowRadius: 8, elevation: 4 }, lg: { shadowColor: shadowColors.dark, shadowOffset: { width: 0, height: 8 }, shadowOpacity: 0.35, shadowRadius: 16, elevation: 8 }, xl: { shadowColor: shadowColors.dark, shadowOffset: { width: 0, height: 12 }, shadowOpacity: 0.4, shadowRadius: 24, elevation: 12 }, xxl: { shadowColor: shadowColors.dark, shadowOffset: { width: 0, height: 16 }, shadowOpacity: 0.45, shadowRadius: 32, elevation: 16 } }; ({ /** * Card shadow. */ card: lightShadows.sm, /** * Button shadow (when elevated). */ button: lightShadows.xs, /** * Pressed button shadow (reduced). */ buttonPressed: lightShadows.none, /** * Floating action button shadow. */ fab: lightShadows.md, /** * Dropdown/Popover shadow. */ dropdown: lightShadows.md, /** * Modal/Dialog shadow. */ modal: lightShadows.lg, /** * Bottom sheet shadow. */ sheet: lightShadows.xl, /** * Toast notification shadow. */ toast: lightShadows.md, /** * Navigation header shadow. */ header: lightShadows.xs, /** * Tab bar shadow. */ tabBar: lightShadows.xs }); // src/design-system/tokens/animation.ts var duration = { instant: 0, fastest: 50, faster: 100, fast: 150, normal: 250, slow: 350, slower: 500, slowest: 700 }; var easing = { /** * Linear - constant speed (rarely used for UI). */ linear: [0, 0, 1, 1], /** * Ease In - slow start, fast end. * Use for: Elements leaving the screen. */ easeIn: [0.42, 0, 1, 1], /** * Ease Out - fast start, slow end. * Use for: Elements entering the screen. * This is the most common easing for iOS-style animations. */ easeOut: [0, 0, 0.58, 1], /** * Ease In Out - slow start and end. * Use for: Elements that start and end on screen. */ easeInOut: [0.42, 0, 0.58, 1], /** * Default spring - balanced, natural feel. * iOS default animation spring characteristics. * Use for: Most interactive animations. */ spring: { damping: 15, stiffness: 150, mass: 1 }, /** * Gentle spring - soft, slow settling. * Use for: Subtle movements, floating elements. */ springGentle: { damping: 20, stiffness: 100, mass: 1 }, /** * Bouncy spring - energetic, playful feel. * Use for: Emphasis, celebrations, playful interactions. * Use sparingly to avoid overwhelming users. */ springBouncy: { damping: 10, stiffness: 200, mass: 1 } }; var animation = { duration, easing }; ({ /** * Button press feedback. */ buttonPress: { duration: duration.faster, easing: easing.easeOut }, /** * Button release feedback. */ buttonRelease: { duration: duration.fast, easing: easing.spring }, /** * Modal/Sheet appear. */ modalEnter: { duration: duration.normal, easing: easing.spring }, /** * Modal/Sheet dismiss. */ modalExit: { duration: duration.fast, easing: easing.easeIn }, /** * Page/Screen transition. */ pageTransition: { duration: duration.slow, easing: easing.easeInOut }, /** * Fade in content. */ fadeIn: { duration: duration.normal, easing: easing.easeOut }, /** * Fade out content. */ fadeOut: { duration: duration.fast, easing: easing.easeIn }, /** * Slide in from bottom. */ slideInUp: { duration: duration.normal, easing: easing.spring }, /** * Slide out to bottom. */ slideOutDown: { duration: duration.fast, easing: easing.easeIn }, /** * Scale up (appearing). */ scaleIn: { duration: duration.normal, easing: easing.springBouncy }, /** * Scale down (disappearing). */ scaleOut: { duration: duration.fast, easing: easing.easeIn }, /** * Expand/Collapse accordion. */ expand: { duration: duration.normal, easing: easing.easeInOut }, /** * Switch/Toggle animation. */ toggle: { duration: duration.fast, easing: easing.spring }, /** * Skeleton loading shimmer. */ skeleton: { duration: duration.slowest, easing: easing.linear }, /** * Toast notification appear. */ toastEnter: { duration: duration.normal, easing: easing.springBouncy }, /** * Toast notification dismiss. */ toastExit: { duration: duration.fast, easing: easing.easeIn }, /** * Haptic feedback timing. */ haptic: { duration: duration.instant, easing: easing.linear } }); ({ /** * Replaces spring/bouncy animations with simple fade. */ default: { duration: duration.fast, easing: easing.easeOut }, /** * Replaces sliding animations with fade. */ slide: { duration: duration.faster, easing: easing.easeOut }, /** * Replaces scale animations with fade. */ scale: { duration: duration.faster, easing: easing.easeOut }, /** * Instant change (no animation). */ instant: { duration: duration.instant, easing: easing.linear } }); // src/design-system/tokens/sizes.ts var sizes = { // Touch targets - Apple HIG minimum 44pt touchTarget: { /** * Minimum touch target size (44pt). * Required by Apple HIG for all interactive elements. */ minimum: 44, /** * Comfortable touch target (48pt). * Recommended for frequently used actions. */ comfortable: 48, /** * Spacious touch target (56pt). * For primary actions and accessibility. */ spacious: 56 }, // Icon sizes icon: { /** * Extra small icon (12pt). * Use for: Inline badges, tiny indicators. */ xs: 12, /** * Small icon (16pt). * Use for: Inline text icons, compact UI. */ sm: 16, /** * Medium icon (20pt). * Use for: Standard inline icons. */ md: 20, /** * Large icon (24pt). * Use for: Navigation icons, tab bar icons. */ lg: 24, /** * Extra large icon (32pt). * Use for: Featured icons, prominent actions. */ xl: 32, /** * XXL icon (40pt). * Use for: Illustrations, large feature icons. */ xxl: 40 }, // Avatar sizes avatar: { /** * Extra small avatar (24pt). * Use for: Inline mentions, compact lists. */ xs: 24, /** * Small avatar (32pt). * Use for: Comments, messaging. */ sm: 32, /** * Medium avatar (40pt). * Use for: Standard list items. */ md: 40, /** * Large avatar (56pt). * Use for: Profile cards, detailed lists. */ lg: 56, /** * Extra large avatar (72pt). * Use for: Profile headers. */ xl: 72, /** * XXL avatar (96pt). * Use for: Profile pages, settings. */ xxl: 96 }, // Button heights button: { /** * Small button (32pt). * Use for: Compact UI, inline actions. * Note: May not meet touch target minimum. */ sm: 32, /** * Medium button (44pt) - DEFAULT. * Use for: Standard buttons. * Meets Apple HIG minimum touch target. */ md: 44, /** * Large button (50pt). * Use for: Primary actions, CTAs. */ lg: 50, /** * Extra large button (56pt). * Use for: Hero actions, onboarding. */ xl: 56 }, // Input heights input: { /** * Small input (36pt). * Use for: Compact forms, filters. */ sm: 36, /** * Medium input (44pt) - DEFAULT. * Use for: Standard form inputs. * Meets Apple HIG minimum touch target. */ md: 44, /** * Large input (52pt). * Use for: Search bars, prominent inputs. */ lg: 52 } }; var zIndex = { /** * Base level - standard content. */ base: 0, /** * Dropdown level - menus, selects. */ dropdown: 1e3, /** * Sticky level - headers, navigation. */ sticky: 1100, /** * Overlay level - background overlays. */ overlay: 1200, /** * Modal level - dialogs, sheets. */ modal: 1300, /** * Popover level - tooltips, popovers. */ popover: 1400, /** * Tooltip level - floating hints. */ tooltip: 1500, /** * Toast level - notifications (highest). */ toast: 1600 }; var breakpoints = { /** * Extra small - small phones. */ xs: 0, /** * Small - standard phones (iPhone SE+). * iPhone SE: 375pt width. */ sm: 375, /** * Medium - large phones (iPhone Pro Max). * iPhone Pro Max: 428pt width. */ md: 428, /** * Large - small tablets (iPad Mini). * iPad Mini portrait: 744pt width. */ lg: 744, /** * Extra large - large tablets (iPad Pro). * iPad Pro portrait: 1024pt width. */ xl: 1024 }; var opacity = { /** * Fully transparent. */ transparent: 0, /** * Disabled state opacity. * iOS uses 0.3-0.4 for disabled elements. */ disabled: 0.38, /** * Medium opacity - overlays, secondary elements. */ medium: 0.6, /** * High opacity - emphasized content. */ high: 0.87, /** * Fully opaque. */ opaque: 1 }; // src/design-system/theme/defaultTheme.ts var lightTheme = { name: "August Light", mode: "light", colors: lightColors, typography, fontFamily, spacing, radius, shadows: lightShadows, animation, sizes, zIndex, breakpoints, opacity }; var darkTheme = { name: "August Dark", mode: "dark", colors: darkColors, typography, fontFamily, spacing, radius, shadows: darkShadows, animation, sizes, zIndex, breakpoints, opacity }; var defaultThemeConfig = { light: lightTheme, dark: darkTheme }; function getTheme(mode) { return mode === "dark" ? darkTheme : lightTheme; } // src/design-system/theme/createTheme.ts function isPlainObject(value) { return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]"; } function deepMerge(target, source) { if (!isPlainObject(target) || !isPlainObject(source)) { return source ?? target; } const output = { ...target }; const sourceObj = source; const targetObj = target; for (const key in sourceObj) { if (Object.prototype.hasOwnProperty.call(sourceObj, key)) { const sourceValue = sourceObj[key]; const targetValue = targetObj[key]; if (isPlainObject(sourceValue) && isPlainObject(targetValue)) { output[key] = deepMerge(targetValue, sourceValue); } else if (sourceValue !== void 0) { output[key] = sourceValue; } } } return output; } function createLightTheme(name, extension = {}) { const baseTheme = { ...lightTheme, name }; return deepMerge(baseTheme, extension); } function createDarkTheme(name, extension = {}) { const baseTheme = { ...darkTheme, name }; return deepMerge(baseTheme, extension); } function createTheme(config) { return { light: createLightTheme(`${config.name} Light`, config.light), dark: createDarkTheme(`${config.name} Dark`, config.dark) }; } function createBrandColors(primary, options = {}) { return { colors: { interactive: { tint: primary, tintPressed: options.primaryPressed ?? primary, tintDisabled: options.primaryDisabled ?? `${primary}4D` // 30% opacity } } }; } function createCustomTypography(fontFamilies) { return { fontFamily: { regular: fontFamilies.regular ?? "System", medium: fontFamilies.medium ?? "System", semibold: fontFamilies.semibold ?? "System", bold: fontFamilies.bold ?? "System", heavy: "System", monospace: "Menlo", rounded: "System" } }; } function mergeExtensions(...extensions) { return extensions.reduce( (acc, ext) => deepMerge(acc, ext), {} ); } function isValidTheme(theme) { if (!isPlainObject(theme)) return false; const requiredKeys = [ "name", "mode", "colors", "typography", "fontFamily", "spacing", "radius", "shadows", "animation", "sizes", "zIndex", "breakpoints", "opacity" ]; return requiredKeys.every((key) => key in theme); } function getTokenValue(theme, path) { const keys = path.split("."); let current = theme; for (const key of keys) { if (!isPlainObject(current) || !(key in current)) { return void 0; } current = current[key]; } return current; } var defaultContextValue = { theme: lightTheme, colorMode: "light", colorModePreference: "system", toggleColorMode: () => { console.warn("ThemeProvider not found in component tree"); }, setColorMode: () => { console.warn("ThemeProvider not found in component tree"); }, isDark: false, isLight: true }; var ThemeContext = React.createContext(defaultContextValue); function ThemeProvider({ children, defaultColorMode = "system", theme: customTheme, storageKey = "august-color-mode" }) { const systemColorScheme = reactNative.useColorScheme(); const [colorModePreference, setColorModePreference] = React.useState(defaultColorMode); const colorMode = React.useMemo(() => { if (colorModePreference === "system") { return systemColorScheme === "dark" ? "dark" : "light"; } return colorModePreference; }, [colorModePreference, systemColorScheme]); const themes = React.useMemo(() => { if (customTheme) { return { light: createLightTheme( customTheme.name ? `${customTheme.name} Light` : "Custom Light", customTheme.light ), dark: createDarkTheme( customTheme.name ? `${customTheme.name} Dark` : "Custom Dark", customTheme.dark ) }; } return { light: lightTheme, dark: darkTheme }; }, [customTheme]); const currentTheme = React.useMemo(() => { return colorMode === "dark" ? themes.dark : themes.light; }, [colorMode, themes]); const toggleColorMode = React.useCallback(() => { setColorModePreference((prev) => { if (prev === "system") { return colorMode === "dark" ? "light" : "dark"; } return prev === "dark" ? "light" : "dark"; }); }, [colorMode]); const setColorMode = React.useCallback((mode) => { setColorModePreference(mode); }, []); const contextValue = React.useMemo( () => ({ theme: currentTheme, colorMode, colorModePreference, toggleColorMode, setColorMode, isDark: colorMode === "dark", isLight: colorMode === "light" }), [ currentTheme, colorMode, colorModePreference, toggleColorMode, setColorMode ] ); return /* @__PURE__ */ React__default.default.createElement(ThemeContext.Provider, { value: contextValue }, children); } function useTheme() { const context = React.useContext(ThemeContext); if (context === defaultContextValue) { console.warn( "useTheme must be used within a ThemeProvider. Falling back to default light theme." ); } return context; } function useThemeTokens() { const { theme } = useTheme(); return theme; } function useColorMode() { const { colorMode } = useTheme(); return colorMode; } function useIsDarkMode() { const { isDark } = useTheme(); return isDark; } function useToken(selector) { const { theme } = useTheme(); return React.useMemo(() => selector(theme), [theme, selector]); } function useColors() { const { theme } = useTheme(); return theme.colors; } function useSpacing() { const { theme } = useTheme(); return theme.spacing; } function useTypography() { const { theme } = useTheme(); return theme.typography; } exports.ThemeContext = ThemeContext; exports.ThemeProvider = ThemeProvider; exports.createBrandColors = createBrandColors; exports.createCustomTypography = createCustomTypography; exports.createDarkTheme = createDarkTheme; exports.createLightTheme = createLightTheme; exports.createTheme = createTheme; exports.darkTheme = darkTheme; exports.defaultThemeConfig = defaultThemeConfig; exports.getTheme = getTheme; exports.getTokenValue = getTokenValue; exports.isValidTheme = isValidTheme; exports.lightTheme = lightTheme; exports.mergeExtensions = mergeExtensions; exports.useColorMode = useColorMode; exports.useColors = useColors; exports.useIsDarkMode = useIsDarkMode; exports.useSpacing = useSpacing; exports.useTheme = useTheme; exports.useThemeTokens = useThemeTokens; exports.useToken = useToken; exports.useTypography = useTypography; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map