august-design-system
Version:
A comprehensive React Native design system following Apple Human Interface Guidelines
2,225 lines (2,212 loc) • 285 kB
JavaScript
'use strict';
var React19 = require('react');
var reactNative = require('react-native');
var MaterialIcons = require('react-native-vector-icons/MaterialIcons');
var Animated6 = require('react-native-reanimated');
var reactNativeSafeAreaContext = require('react-native-safe-area-context');
var Svg = require('react-native-svg');
var reactNativeGestureHandler = require('react-native-gesture-handler');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var React19__default = /*#__PURE__*/_interopDefault(React19);
var MaterialIcons__default = /*#__PURE__*/_interopDefault(MaterialIcons);
var Animated6__default = /*#__PURE__*/_interopDefault(Animated6);
var Svg__default = /*#__PURE__*/_interopDefault(Svg);
// 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)"
}
};
function withAlpha(color, alpha) {
if (color.startsWith("rgba")) {
return color.replace(/[\d.]+\)$/, `${alpha})`);
}
if (color.startsWith("#")) {
const hex = color.replace("#", "");
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
return color;
}
function hasMinimumContrast(foreground, background, minimumRatio = 4.5) {
const isDarkBg = background === "#000000" || background.includes("1C1C1E") || background.includes("2C2C2E");
const isLightFg = foreground === "#FFFFFF" || foreground.includes("235, 235, 245");
return isDarkBg === isLightFg;
}
// 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 withSize(style, fontSize) {
const ratio = style.lineHeight / style.fontSize;
return {
...style,
fontSize,
lineHeight: Math.round(fontSize * ratio)
};
}
function emphasized(style) {
return withWeight(style, "600");
}
function bold(style) {
return withWeight(style, "700");
}
var typographyEmphasis = {
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_UNIT = 4;
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
}
};
var layoutConstants = {
/**
* Standard horizontal margin for content.
* iOS typically uses 16pt margins.
*/
screenHorizontalPadding: 16,
/**
* Standard vertical margin for content.
*/
screenVerticalPadding: 16,
/**
* Navigation bar height (standard).
*/
navigationBarHeight: 44,
/**
* Navigation bar height (large title).
*/
navigationBarLargeTitleHeight: 96,
/**
* Tab bar height.
*/
tabBarHeight: 49,
/**
* Tab bar height with home indicator (iPhone X+).
*/
tabBarHeightWithHomeIndicator: 83,
/**
* Minimum touch target size (Apple HIG requirement).
* All interactive elements should be at least 44x44pt.
*/
minTouchTarget: 44,
/**
* Standard list item height.
*/
listItemHeight: 44,
/**
* Standard list item height (subtitle style).
*/
listItemSubtitleHeight: 64,
/**
* Standard search bar height.
*/
searchBarHeight: 36,
/**
* Standard toolbar height.
*/
toolbarHeight: 44,
/**
* Standard separator thickness.
*/
separatorThickness: 0.5,
/**
* Standard icon size in lists.
*/
listIconSize: 28,
/**
* Disclosure indicator width.
*/
disclosureIndicatorWidth: 8,
/**
* Standard button corner radius.
*/
buttonCornerRadius: 10,
/**
* Standard card corner radius.
*/
cardCornerRadius: 12,
/**
* Sheet corner radius.
*/
sheetCornerRadius: 16
};
function space(multiplier) {
return SPACING_UNIT * multiplier;
}
function insetAll(value) {
return {
padding: value
};
}
function insetSquish(horizontal, vertical) {
return {
paddingHorizontal: horizontal,
paddingVertical: vertical
};
}
function insetDirectional(top, right, bottom, left) {
return {
paddingTop: top,
paddingRight: right,
paddingBottom: bottom,
paddingLeft: left
};
}
// src/design-system/tokens/radius.ts
var radius = {
none: 0,
xs: 4,
sm: 8,
md: 12,
lg: 16,
xl: 20,
xxl: 24,
full: 9999
};
var semanticRadius = {
/**
* 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
};
function circular(size) {
return size / 2;
}
function corners(topLeft, topRight, bottomRight, bottomLeft) {
return {
borderTopLeftRadius: topLeft,
borderTopRightRadius: topRight,
borderBottomRightRadius: bottomRight,
borderBottomLeftRadius: bottomLeft
};
}
function topRounded(value) {
return corners(value, value, 0, 0);
}
function bottomRounded(value) {
return corners(0, 0, value, value);
}
function leftRounded(value) {
return corners(value, 0, 0, value);
}
function rightRounded(value) {
return corners(0, value, value, 0);
}
// 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
}
};
var semanticShadows = {
/**
* 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
};
function createShadow(offsetY, opacity2, radius2, elevation, offsetX = 0, color = shadowColors.light) {
return {
shadowColor: color,
shadowOffset: { width: offsetX, height: offsetY },
shadowOpacity: opacity2,
shadowRadius: radius2,
elevation
};
}
function combineShadows(...shadows) {
if (shadows.length === 0) return lightShadows.none;
return shadows.reduce(
(prev, current) => current.elevation > prev.elevation ? current : prev
);
}
function scaleShadow(shadow, factor) {
return {
...shadow,
shadowOffset: {
width: shadow.shadowOffset.width * factor,
height: shadow.shadowOffset.height * factor
},
shadowRadius: shadow.shadowRadius * factor,
elevation: Math.round(shadow.elevation * factor)
};
}
// 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
};
var animationPresets = {
/**
* 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
}
};
var reducedMotionPresets = {
/**
* 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
}
};
function withDelay(baseDelay, index = 0, staggerAmount = 50) {
return baseDelay + index * staggerAmount;
}
function stagger(index, staggerAmount = 50, maxDelay = 500) {
return Math.min(index * staggerAmount, maxDelay);
}
// 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
};
var componentSizes = {
/**
* Navigation bar heights.
*/
navigationBar: {
standard: 44,
large: 96,
largeExpanded: 140
},
/**
* Tab bar heights.
*/
tabBar: {
standard: 49,
withHomeIndicator: 83
},
/**
* Search bar dimensions.
*/
searchBar: {
height: 36,
iconSize: 18
},
/**
* Toolbar dimensions.
*/
toolbar: {
height: 44,
iconSize: 24
},
/**
* Segmented control.
*/
segmentedControl: {
height: 32,
minSegmentWidth: 60
},
/**
* Switch/Toggle.
*/
switch: {
width: 51,
height: 31,
thumbSize: 27
},
/**
* Slider.
*/
slider: {
trackHeight: 4,
thumbSize: 28
},
/**
* Progress bar.
*/
progressBar: {
height: 4,
heightLarge: 8
},
/**
* Badge.
*/
badge: {
minWidth: 20,
height: 20,
dotSize: 8
},
/**
* Chip/Tag.
*/
chip: {
height: 32,
heightSmall: 24
},
/**
* List item.
*/
listItem: {
standard: 44,
subtitle: 64,
large: 88
},
/**
* Card.
*/
card: {
minHeight: 80,
imageAspectRatio: 16 / 9
},
/**
* Modal.
*/
modal: {
maxWidth: 540,
minHeight: 200
},
/**
* Sheet.
*/
sheet: {
handleWidth: 36,
handleHeight: 5,
snapPoints: {
collapsed: 0.25,
half: 0.5,
expanded: 0.9
}
},
/**
* Toast.
*/
toast: {
minHeight: 48,
maxWidth: 400
}
};
function meetsMinimumTouchTarget(size) {
return size >= sizes.touchTarget.minimum;
}
function ensureMinimumTouchTarget(size) {
return Math.max(size, sizes.touchTarget.minimum);
}
function getIconSizeForContext(context) {
switch (context) {
case "inline":
return sizes.icon.sm;
case "navigation":
return sizes.icon.lg;
case "tabBar":
return sizes.icon.lg;
case "feature":
return sizes.icon.xl;
default:
return sizes.icon.md;
}
}
// 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 = React19.createContext(defaultContextValue);
function ThemeProvider({
children,
defaultColorMode = "system",
theme: customTheme,
storageKey = "august-color-mode"
}) {
const systemColorScheme = reactNative.useColorScheme();
const [colorModePreference, setColorModePreference] = React19.useState(defaultColorMode);
const colorMode = React19.useMemo(() => {
if (colorModePreference === "system") {
return systemColorScheme === "dark" ? "dark" : "light";
}
return colorModePreference;
}, [colorModePreference, systemColorScheme]);
const themes = React19.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 = React19.useMemo(() => {
return colorMode === "dark" ? themes.dark : themes.light;
}, [colorMode, themes]);
const toggleColorMode = React19.useCallback(() => {
setColorModePreference((prev) => {
if (prev === "system") {
return colorMode === "dark" ? "light" : "dark";
}
return prev === "dark" ? "light" : "dark";
});
}, [colorMode]);
const setColorMode = React19.useCallback((mode) => {
setColorModePreference(mode);
}, []);
const contextValue = React19.useMemo(
() => ({
theme: currentTheme,
colorMode,
colorModePreference,
toggleColorMode,
setColorMode,
isDark: colorMode === "dark",
isLight: colorMode === "light"
}),
[
currentTheme,
colorMode,
colorModePreference,
toggleColorMode,
setColorMode
]
);
return /* @__PURE__ */ React19__default.default.createElement(ThemeContext.Provider, { value: contextValue }, children);
}
function useTheme() {
const context = React19.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 React19.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;
}
function useThemedStyles(styleCreator) {
const { theme } = useTheme();
return React19.useMemo(() => {
const rawStyles = styleCreator(theme);
return reactNative.StyleSheet.create(rawStyles);
}, [theme, styleCreator]);
}
function useThemedStyle(styleCreator) {
const { theme } = useTheme();
return React19.useMemo(() => styleCreator(theme), [theme, styleCreator]);
}
function createThemedStyles(styleCreator) {
return function useStyles() {
return useThemedStyles(styleCreator);
};
}
function combineStyles(...styles3) {
return styles3.filter(Boolean);
}
function conditionalStyle(condition, trueStyle, falseStyle) {
if (condition) return trueStyle;
return falseStyle;
}
function useBreakpoint() {
const { width } = reactNative.useWindowDimensions();
const { theme } = useTheme();
const { breakpoints: breakpoints2 } = theme;
return React19.useMemo(() => {
if (width >= breakpoints2.xl) return "xl";
if (width >= breakpoints2.lg) return "lg";
if (width >= breakpoints2.md) return "md";
if (width >= breakpoints2.sm) return "sm";
return "xs";
}, [width, breakpoints2]);
}
function useResponsiveValue(value) {
const breakpoint = useBreakpoint();
return React19.useMemo(() => {
if (typeof value !== "object" || value === null || Array.isArray(value)) {
return value;
}
const responsiveValue = value;
const breakpointOrder = ["xl", "lg", "md", "sm", "xs"];
const currentIndex = breakpointOrder.indexOf(breakpoint);
for (let i = currentIndex; i < breakpointOrder.length; i++) {
const bp = breakpointOrder[i];
if (bp in responsiveValue && responsiveValue[bp] !== void 0) {
return responsiveValue[bp];
}
}
for (const bp of breakpointOrder) {
if (bp in responsiveValue && responsiveValue[bp] !== void 0) {
return responsiveValue[bp];
}
}
return void 0;
}, [value, breakpoint]);
}
function useDeviceType() {
const breakpoint = useBreakpoint();
return breakpoint === "lg" || breakpoint === "xl" ? "tablet" : "phone";
}
function useIsBreakpoint(targetBreakpoint) {
const { width } = reactNative.useWindowDimensions();
const { theme } = useTheme();
return width >= theme.breakpoints[targetBreakpoint];
}
function useScreenDimensions() {
const { width, height } = reactNative.useWindowDimensions();
return React19.useMemo(
() => ({
width,
height,
isPortrait: height >= width,
isLandscape: width > height,
aspectRatio: width / height
}),
[width, height]
);
}
function responsiveStyle(styles3) {
const breakpointOrder = ["xl", "lg", "md", "sm", "xs"];
return (breakpoint) => {
const currentIndex = breakpointOrder.indexOf(breakpoint);
for (let i = currentIndex; i < breakpointOrder.length; i++) {
const bp = breakpointOrder[i];
if (bp in styles3 && styles3[bp] !== void 0) {
return styles3[bp];
}
}
return void 0;
};
}
function useReducedMotion() {
const [reducedMotion, setReducedMotion] = React19.useState(false);
React19.useEffect(() => {
reactNative.AccessibilityInfo.isReduceMotionEnabled().then(setReducedMotion);
const subscription = reactNative.AccessibilityInfo.addEventListener(
"reduceMotionChanged",
setReducedMotion
);
return () => {
subscription.remove();
};
}, []);
return reducedMotion;
}
function useAccessibleAnimation(preset) {
const prefersReducedMotion = useReducedMotion();
return React19.useMemo(() => {
if (prefersReducedMotion) {
return {
duration: reducedMotionPresets.default.duration,
useNativeDriver: true,
isReduced: true
};
}
return {
duration: animationPresets[preset].duration,
useNativeDriver: true,
isReduced: false
};
}, [preset, prefersReducedMotion]);
}
function useScreenReader() {
const [screenReaderEnabled, setScreenReaderEnabled] = React19.useState(false);
React19.useEffect(() => {
reactNative.AccessibilityInfo.isScreenReaderEnabled().then(setScreenReaderEnabled);
const subscription = reactNative.AccessibilityInfo.addEventListener(
"screenReaderChanged",
setScreenReaderEnabled
);
return () => {
subscription.remove();
};
}, []);
return screenReaderEnabled;
}
function useBoldText() {
const [boldTextEnabled, setBoldTextEnabled] = React19.useState(false);
React19.useEffect(() => {
reactNative.AccessibilityInfo.isBoldTextEnabled().then(setBoldTextEnabled);
const subscription = reactNative.AccessibilityInfo.addEventListener(
"boldTextChanged",
setBoldTextEnabled
);
return () => {
subscription.remove();
};
}, []);
return boldTextEnabled;
}
function useDynamicType() {
const { fontScale } = reactNative.useWindowDimensions();
return fontScale;
}
function useScaledTypography(baseStyle, options = {}) {
const { maxScale = 2, minScale = 0.8 } = options;
const fontScale = useDynamicType();
return React19.useMemo(() => {
const clampedScale = Math.min(Math.max(fontScale, minScale), maxScale);
return {
...baseStyle,
fontSize: Math.round(baseStyle.fontSize * clampedScale),
lineHeight: Math.round(baseStyle.lineHeight * clampedScale)
};
}, [baseStyle, fontScale, maxScale, minScale]);
}
function useHighContrast() {
const boldTextEnabled = useBoldText();
return boldTextEnabled;
}
function announceForAccessibility(message) {
reactNative.AccessibilityInfo.announceForAccessibility(message);
}
function setAccessibilityFocus(reactTag) {
if (reactTag) {
reactNative.AccessibilityInfo.setAccessibilityFocus(reactTag);
}
}
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
function rgbToHex(r, g, b) {
return "#" + [r, g, b].map((x) => {
const hex = Math.round(x).toString(16);
return hex.length === 1 ? "0" + hex : hex;
}).join("");
}
function withOpacity(color, alpha) {
if (color.startsWith("rgba")) {
return color.replace(/[\d.]+\)$/, `${alpha})`);
}
if (color.startsWith("rgb(")) {
return color.replace("rgb(", "rgba(").replace(")", `, ${alpha})`);
}
if (color.startsWith("#")) {
const rgb = hexToRgb(color);
if (rgb) {
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
}
}
return color;
}
function lighten(color, percent) {
const rgb = hexToRgb(color);
if (!rgb) return color;
const factor = percent / 100;
return rgbToHex(
Math.min(255, rgb.r + (255 - rgb.r) * factor),
Math.min(255, rgb.g + (255 - rgb.g) * factor),
Math.min(255, rgb.b + (255 - rgb.b) * factor)
);
}
function darken(color, percent) {
const rgb = hexToRgb(color);
if (!rgb) return color;
const factor = 1 - percent / 100;
return rgbToHex(rgb.r * factor, rgb.g * factor, rgb.b * factor);
}
function getLuminance(color) {
const rgb = hexToRgb(color);
if (!rgb) return 0;
const [r, g, b] = [rgb.r, rgb.g, rgb.b].map((channel) => {
const sRGB = channel / 255;
return sRGB <= 0.03928 ? sRGB / 12.92 : Math.pow((sRGB + 0.055) / 1.055, 2.4);
});
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
function getContrastRatio(color1, color2) {
const lum1 = getLuminance(color1);
const lum2 = getLuminance(color2);
const lighter = Math.max(lum1, lum2);
const darker = Math.min(lum1, lum2);
return (lighter + 0.05) / (darker + 0.05);
}
function meetsWCAGAA(ratio, isLargeText = false) {
return isLargeText ? ratio >= 3 : ratio >= 4.5;
}
function meetsWCAGAAA(ratio, isLargeText = false) {
return isLargeText ? ratio >= 4.5 : ratio >= 7;
}
function gridSpace(multiplier) {
return multiplier * 4;
}
function clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
function get(obj, path, defaultValue) {
const keys = path.split(".");
let result = obj;
for (const key of keys) {
if (result === null || result === void 0) {
return defaultValue;
}
result = result[key];
}
return result ?? defaultValue;
}
function getColor(theme, colorPath) {
return get(theme.colors, colorPath, "");
}
function ios(iosValue, androidValue) {
return reactNative.Platform.OS === "ios" ? iosValue : androidValue;
}
function android(androidValue, iosValue) {
return reactNative.Platform.OS === "android" ? androidValue : iosValue;
}
function platformSelect(options) {
if (reactNative.Platform.OS === "ios" && options.ios !== void 0) {
return options.ios;
}
if (reactNative.Platform.OS === "android" && options.android !== void 0) {
return options.android;
}
return options.default;
}
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
function toKebabCase(str) {
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/\s+/g, "-").toLowerCase();
}
function toCamelCase(str) {
return str.replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : "").replace(/^(.)/, (c) => c.toLowerCase());
}
// src/design-system/constants/index.ts
var VERSION = "1.0.0";
var NAME = "AugustDesignSystem";
var HIG = {
/**
* Minimum touch target size in points.
* All interactive elements must be at least this size.
*/
MIN_TOUCH_TARGET: 44,
/**
* Recommended touch target size for comfortable interaction.
*/
COMFORTABLE_TOUCH_TARGET: 48,
/**
* Standard iOS content margins.
*/
CONTENT_MARGIN: 16,
/**
* Standard iOS safe area additional padding.
*/
SAFE_AREA_PADDING: 16,
/**
* Navigation bar heights.
*/
NAV_BAR_HEIGHT: 44,
NAV_BAR_LARGE_TITLE_HEIGHT: 96,
/**
* Tab bar heights.
*/
TAB_BAR_HEIGHT: 49,
TAB_BAR_HEIGHT_WITH_HOME_INDICATOR: 83,
/**
* Home indicator height (iPhone X and later).
*/
HOME_INDICATOR_HEIGHT: 34,
/**
* Status bar heights.
*/
STATUS_BAR_HEIGHT: 44,
// iPhone X+
STATUS_BAR_HEIGHT_LEGACY: 20,
// Older iPhones
/**
* Keyboard heights (approximate, varies by device).
*/
KEYBOARD_HEIGHT_PORTRAIT: 291,
KEYBOARD_HEIGHT_LANDSCAPE: 209,
/**
* Standard list item heights.
*/
LIST_ITEM_HEIGHT: 44,
LIST_ITEM_SUBTITLE_HEIGHT: 64,
/**
* Separator line thickness.
*/
SEPARATOR_HEIGHT: 0.5,
/**
* Standard animation durations (in ms).
*/
ANIMATION_FAST: 150,
ANIMATION_NORMAL: 250,
ANIMATION_SLOW: 350,
/**
* Modal presentation heights.
*/
SHEET_PEEK_HEIGHT: 0.25,
SHEET_HALF_HEIGHT: 0.5,
SHEET_FULL_HEIGHT: 0.9
};
var ACCESSIBILITY = {
/**
* Minimum contrast ratio for normal text (WCAG AA).
*/
MIN_CONTRAST_RATIO: 4.5,
/**
* Minimum contrast ratio for large text (WCAG AA).
*/
MIN_CONTRAST_RATIO_LARGE: 3,
/**
* Enhanced contrast ratio for normal text (WCAG AAA).
*/
ENHANCED_CONTRAST_RATIO: 7,
/**
* Enhanced contrast ratio for large text (WCAG AAA).
*/
ENHANCED_CONTRAST_RATIO_LARGE: 4.5,
/**
* Large text threshold (18pt regular or 14pt bold).
*/
LARGE_TEXT_THRESHOLD: 18,
LARGE_TEXT_BOLD_THRESHOLD: 14,
/**
* Maximum text scale factor for accessibility.
*/
MAX_FONT_SCALE: 3.1,
/**
* Minimum recommended line height ratio.
*/
MIN_LINE_HEIGHT_RATIO: 1.2
};
var PLATFORM = {
/**
* iOS system font name.
*/
IOS_FONT: "System",
/**
* Android system font name.
*/
ANDROID_FONT: "Roboto",
/**
* Monospace font fallbacks.
*/
MONOSPACE_IOS: "Menlo",
MONOSPACE_ANDROID: "monospace",
/**
* Default shadow color.
*/
SHADOW_COLOR: "#000000"
};
var Z_INDEX = {
BASE: 0,
DROPDOWN: 1e3,
STICKY: 1100,
OVERLAY: 1200,
MODAL: 1300,
POPOVER: 1400,
TOOLTIP: 1500,
TOAST: 1600
};
var GRID = {
/**
* Base unit for spacing (4pt grid).
*/
BASE_UNIT: 4,
/**
* Common grid multipliers.
*/
MULTIPLIERS: {
HALF: 0.5,
// 2pt
SINGLE: 1,
// 4pt
DOUBLE: 2,
// 8pt
TRIPLE: 3,
// 12pt
QUAD: 4,
// 16pt
QUINT: 5,
// 20pt
HEX: 6,
// 24pt
OCTA: 8,
// 32pt
DECA: 10,
// 40pt
DODECA: 12
// 48pt
}
};
var BREAKPOINTS = {
/**
* Small phones.
*/
XS: 0,
/**
* Standard phones (iPhone SE and up).
*/
SM: 375,
/**
* Large phones (iPhone Pro Max).
*/
MD: 428,
/**
* Small tablets (iPad Mini).
*/
LG: 744,
/**
* Large tablets (iPad Pro).
*/
XL: 1024
};
var TIMING = {
/**
* Debounce delay for search inputs (ms).
*/
DEBOUNCE_SEARCH: 300,
/**
* Debounce delay for resize events (ms).
*/
DEBOUNCE_RESIZE: 150,
/**
* Long press threshold (ms).
*/
LONG_PRESS_DELAY: 500,
/**
* Double tap threshold (ms)