{
  "$schema": "https://ui.shadcn.com/schema/registry.json",
  "name": "intelli-ui-native",
  "homepage": "https://ui.intellihelper.in/native",
  "items": [
    {
      "name": "native-theme",
      "type": "registry:lib",
      "title": "Native Theme",
      "description": "Liquid Glass theme tokens and ThemeProvider for React Native.",
      "meta": {
        "platform": "native"
      },
      "files": [
        {
          "path": "packages/ui-native/src/theme/colors.ts",
          "type": "registry:lib",
          "target": "components/ui/native/theme/colors.ts",
          "content": "/**\n * Semantic + glass chrome palettes.\n * Approximates web oklch / color-mix tokens as RN-safe hex/rgba.\n */\n\nexport interface ThemeColors {\n  background: string;\n  foreground: string;\n  surface: string;\n  card: string;\n  cardForeground: string;\n  popover: string;\n  popoverForeground: string;\n  primary: string;\n  primaryForeground: string;\n  secondary: string;\n  secondaryForeground: string;\n  muted: string;\n  mutedForeground: string;\n  accent: string;\n  accentForeground: string;\n  destructive: string;\n  destructiveForeground: string;\n  border: string;\n  input: string;\n  ring: string;\n  success: string;\n  successForeground: string;\n  /** Glass chrome (neutral frosted surfaces) */\n  glassChromeBg: string;\n  glassChromeBgEnv: string;\n  glassChromeFg: string;\n  glassChromeFgMuted: string;\n  glassChromeBorder: string;\n  glassSurfaceFill: string;\n  glassButtonUiBg: string;\n  glassButtonUiBgHover: string;\n  glassButtonUiFg: string;\n  glassButtonUiBorder: string;\n  glassIndicatorBg: string;\n  glassIndicatorBorder: string;\n  contentText: string;\n  contentTextMuted: string;\n  overlay: string;\n  overlayHeavy: string;\n}\n\nexport const monoLight: ThemeColors = {\n  background: \"#ffffff\",\n  foreground: \"#1a1a1a\",\n  surface: \"#ffffff\",\n  card: \"rgba(255,255,255,0.92)\",\n  cardForeground: \"#1a1a1a\",\n  popover: \"rgba(255,255,255,0.96)\",\n  popoverForeground: \"#1a1a1a\",\n  primary: \"#1a1a1a\",\n  primaryForeground: \"#fafafa\",\n  secondary: \"#f5f5f5\",\n  secondaryForeground: \"#2a2a2a\",\n  muted: \"#f0f0f0\",\n  mutedForeground: \"#6b6b6b\",\n  accent: \"#2a2a2a\",\n  accentForeground: \"#fafafa\",\n  destructive: \"#5c5c5c\",\n  destructiveForeground: \"#fafafa\",\n  border: \"rgba(0,0,0,0.14)\",\n  input: \"rgba(0,0,0,0.06)\",\n  ring: \"rgba(26,26,26,0.35)\",\n  success: \"#2d8a4e\",\n  successForeground: \"#fafafa\",\n  /* Apple Liquid Glass — milky frost (matches web tokens) */\n  glassChromeBg: \"rgba(247,247,247,0.72)\",\n  glassChromeBgEnv: \"rgba(250,250,250,0.78)\",\n  glassChromeFg: \"#1f1f1f\",\n  glassChromeFgMuted: \"#666666\",\n  glassChromeBorder: \"rgba(20,20,20,0.12)\",\n  glassSurfaceFill: \"rgba(252,252,252,0.78)\",\n  glassButtonUiBg: \"rgba(255,255,255,0.62)\",\n  glassButtonUiBgHover: \"rgba(255,255,255,0.74)\",\n  glassButtonUiFg: \"#1f1f1f\",\n  glassButtonUiBorder: \"rgba(20,20,20,0.14)\",\n  glassIndicatorBg: \"rgba(255,255,255,0.96)\",\n  glassIndicatorBorder: \"rgba(20,20,20,0.09)\",\n  contentText: \"#fafafa\",\n  contentTextMuted: \"rgba(250,250,250,0.72)\",\n  overlay: \"rgba(0,0,0,0.22)\",\n  overlayHeavy: \"rgba(0,0,0,0.45)\",\n};\n\nexport const monoDark: ThemeColors = {\n  background: \"#141414\",\n  foreground: \"#f5f5f5\",\n  surface: \"#1f1f1f\",\n  card: \"rgba(30,30,34,0.88)\",\n  cardForeground: \"#f5f5f5\",\n  popover: \"rgba(22,22,26,0.94)\",\n  popoverForeground: \"#f5f5f5\",\n  primary: \"#f5f5f5\",\n  primaryForeground: \"#141414\",\n  secondary: \"#2e2e2e\",\n  secondaryForeground: \"#e8e8e8\",\n  muted: \"#262626\",\n  mutedForeground: \"#9a9a9a\",\n  accent: \"#d4d4d4\",\n  accentForeground: \"#141414\",\n  destructive: \"#8a8a8a\",\n  destructiveForeground: \"#fafafa\",\n  border: \"rgba(255,255,255,0.18)\",\n  input: \"rgba(255,255,255,0.08)\",\n  ring: \"rgba(245,245,245,0.35)\",\n  success: \"#4ade80\",\n  successForeground: \"#0a0a0a\",\n  /* Dense smoked glass — matches web dark Liquid Glass */\n  glassChromeBg: \"rgba(48,50,62,0.68)\",\n  glassChromeBgEnv: \"rgba(52,54,68,0.72)\",\n  glassChromeFg: \"#f5f5f7\",\n  glassChromeFgMuted: \"rgba(240,240,245,0.74)\",\n  glassChromeBorder: \"rgba(255,255,255,0.16)\",\n  glassSurfaceFill: \"rgba(34,36,48,0.74)\",\n  glassButtonUiBg: \"rgba(58,62,78,0.62)\",\n  glassButtonUiBgHover: \"rgba(66,70,88,0.72)\",\n  glassButtonUiFg: \"#f5f5f7\",\n  glassButtonUiBorder: \"rgba(255,255,255,0.2)\",\n  glassIndicatorBg: \"rgba(36,38,50,0.95)\",\n  glassIndicatorBorder: \"rgba(255,255,255,0.14)\",\n  contentText: \"#fafafa\",\n  contentTextMuted: \"rgba(250,250,250,0.72)\",\n  overlay: \"rgba(0,0,0,0.45)\",\n  overlayHeavy: \"rgba(0,0,0,0.65)\",\n};\n"
        },
        {
          "path": "packages/ui-native/src/theme/index.ts",
          "type": "registry:lib",
          "target": "components/ui/native/theme/index.ts",
          "content": "export type { ThemeColors } from \"./colors\";\nexport { monoDark, monoLight } from \"./colors\";\nexport {\n  createTheme,\n  defaultTheme,\n  type ColorMode,\n  type Theme,\n  type ThemeId,\n} from \"./themes\";\nexport {\n  ThemeProvider,\n  useColors,\n  useTheme,\n  type ThemeProviderProps,\n} from \"./provider\";\nexport {\n  durations,\n  fontSizes,\n  fontWeights,\n  lineHeights,\n  radii,\n  spacing,\n  zIndex,\n} from \"./tokens\";\n"
        },
        {
          "path": "packages/ui-native/src/theme/provider.tsx",
          "type": "registry:lib",
          "target": "components/ui/native/theme/provider.tsx",
          "content": "import {\n  createContext,\n  useCallback,\n  useContext,\n  useMemo,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport { useColorScheme } from \"react-native\";\nimport type { ThemeColors } from \"./colors\";\nimport {\n  createTheme,\n  type ColorMode,\n  type Theme,\n  type ThemeId,\n} from \"./themes\";\n\nexport interface ThemeProviderProps {\n  children: ReactNode;\n  /** Theme id (v1: mono only). */\n  theme?: ThemeId;\n  /** Force light/dark. When omitted, follows system when `followSystem` is true. */\n  mode?: ColorMode;\n  /** Sync with system color scheme when `mode` is not controlled. Default true. */\n  followSystem?: boolean;\n  onModeChange?: (mode: ColorMode) => void;\n}\n\ninterface ThemeContextValue {\n  theme: Theme;\n  colors: ThemeColors;\n  mode: ColorMode;\n  setMode: (mode: ColorMode) => void;\n  toggleMode: () => void;\n}\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\n\nexport function ThemeProvider({\n  children,\n  theme: themeId = \"mono\",\n  mode: controlledMode,\n  followSystem = true,\n  onModeChange,\n}: ThemeProviderProps) {\n  const system = useColorScheme();\n  const [internalMode, setInternalMode] = useState<ColorMode>(\n    controlledMode ?? (system === \"dark\" ? \"dark\" : \"light\"),\n  );\n\n  const mode: ColorMode =\n    controlledMode ??\n    (followSystem ? (system === \"dark\" ? \"dark\" : \"light\") : internalMode);\n\n  const setMode = useCallback(\n    (next: ColorMode) => {\n      setInternalMode(next);\n      onModeChange?.(next);\n    },\n    [onModeChange],\n  );\n\n  const toggleMode = useCallback(() => {\n    setMode(mode === \"dark\" ? \"light\" : \"dark\");\n  }, [mode, setMode]);\n\n  const theme = useMemo(() => createTheme(themeId, mode), [themeId, mode]);\n\n  const value = useMemo<ThemeContextValue>(\n    () => ({\n      theme,\n      colors: theme.colors,\n      mode,\n      setMode,\n      toggleMode,\n    }),\n    [theme, mode, setMode, toggleMode],\n  );\n\n  return (\n    <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>\n  );\n}\n\nexport function useTheme(): ThemeContextValue {\n  const ctx = useContext(ThemeContext);\n  if (!ctx) {\n    throw new Error(\"useTheme must be used within a ThemeProvider\");\n  }\n  return ctx;\n}\n\n/** Convenience: theme colors only. */\nexport function useColors(): ThemeColors {\n  return useTheme().colors;\n}\n"
        },
        {
          "path": "packages/ui-native/src/theme/themes.ts",
          "type": "registry:lib",
          "target": "components/ui/native/theme/themes.ts",
          "content": "import { monoDark, monoLight, type ThemeColors } from \"./colors\";\nimport {\n  durations,\n  fontSizes,\n  fontWeights,\n  lineHeights,\n  radii,\n  spacing,\n  zIndex,\n} from \"./tokens\";\n\nexport type ColorMode = \"light\" | \"dark\";\nexport type ThemeId = \"mono\";\n\nexport interface Theme {\n  id: ThemeId;\n  mode: ColorMode;\n  colors: ThemeColors;\n  radii: typeof radii;\n  spacing: typeof spacing;\n  durations: typeof durations;\n  fontSizes: typeof fontSizes;\n  fontWeights: typeof fontWeights;\n  lineHeights: typeof lineHeights;\n  zIndex: typeof zIndex;\n}\n\nconst colorMaps: Record<ThemeId, Record<ColorMode, ThemeColors>> = {\n  mono: {\n    light: monoLight,\n    dark: monoDark,\n  },\n};\n\nexport function createTheme(\n  id: ThemeId = \"mono\",\n  mode: ColorMode = \"light\",\n): Theme {\n  return {\n    id,\n    mode,\n    colors: colorMaps[id][mode],\n    radii,\n    spacing,\n    durations,\n    fontSizes,\n    fontWeights,\n    lineHeights,\n    zIndex,\n  };\n}\n\nexport const defaultTheme = createTheme(\"mono\", \"light\");\n"
        },
        {
          "path": "packages/ui-native/src/theme/tokens.ts",
          "type": "registry:lib",
          "target": "components/ui/native/theme/tokens.ts",
          "content": "/** Design tokens mirrored from packages/tokens (CSS → JS). */\n\nexport const radii = {\n  sm: 6,\n  md: 8,\n  lg: 12,\n  xl: 16,\n  \"2xl\": 20,\n  \"3xl\": 24,\n  full: 9999,\n} as const;\n\nexport const spacing = {\n  0: 0,\n  0.5: 2,\n  1: 4,\n  1.5: 6,\n  2: 8,\n  2.5: 10,\n  3: 12,\n  3.5: 14,\n  4: 16,\n  5: 20,\n  6: 24,\n  7: 28,\n  8: 32,\n  10: 40,\n  12: 48,\n  16: 64,\n} as const;\n\nexport const durations = {\n  fast: 100,\n  normal: 200,\n  slow: 300,\n  enter: 450,\n} as const;\n\nexport const fontSizes = {\n  xs: 12,\n  sm: 14,\n  base: 16,\n  lg: 18,\n  xl: 20,\n  \"2xl\": 24,\n  \"3xl\": 30,\n  \"4xl\": 36,\n  \"5xl\": 48,\n} as const;\n\nexport const fontWeights = {\n  normal: \"400\" as const,\n  medium: \"500\" as const,\n  semibold: \"600\" as const,\n  bold: \"700\" as const,\n  extrabold: \"800\" as const,\n};\n\nexport const lineHeights = {\n  tight: 1.15,\n  snug: 1.25,\n  normal: 1.5,\n  relaxed: 1.625,\n} as const;\n\nexport const zIndex = {\n  dropdown: 50,\n  sticky: 100,\n  modal: 200,\n  toast: 300,\n} as const;\n"
        }
      ]
    },
    {
      "name": "native-utils",
      "type": "registry:lib",
      "title": "Native Utils",
      "description": "Style merge and motion helpers for React Native.",
      "meta": {
        "platform": "native"
      },
      "files": [
        {
          "path": "packages/ui-native/src/utils/animation.ts",
          "type": "registry:lib",
          "target": "components/ui/native/utils/animation.ts",
          "content": "import { useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, type ViewStyle } from \"react-native\";\nimport { durations } from \"../theme/tokens\";\n\n/** Spring configs roughly matching web `--ease-spring`. */\nexport const springs = {\n  snappy: { friction: 7, tension: 140, useNativeDriver: true as const },\n  soft: { friction: 9, tension: 80, useNativeDriver: true as const },\n  thumb: { friction: 8, tension: 80, useNativeDriver: true as const },\n} as const;\n\nexport const timings = {\n  fast: durations.fast,\n  normal: durations.normal,\n  slow: durations.slow,\n  enter: durations.enter,\n} as const;\n\nexport function springTo(\n  value: Animated.Value,\n  toValue: number,\n  config: keyof typeof springs = \"snappy\",\n) {\n  return Animated.spring(value, {\n    toValue,\n    ...springs[config],\n  });\n}\n\nexport function timingTo(\n  value: Animated.Value,\n  toValue: number,\n  duration: number = timings.normal,\n  easing = Easing.out(Easing.cubic),\n) {\n  return Animated.timing(value, {\n    toValue,\n    duration,\n    easing,\n    useNativeDriver: true,\n  });\n}\n\n/**\n * Presence animation for overlays (Dialog, Sheet, Select, Popover).\n * Keeps content mounted through the exit animation, then unmounts.\n */\nexport function usePresence(open: boolean, duration: number = timings.normal) {\n  const [mounted, setMounted] = useState(open);\n  const progress = useRef(new Animated.Value(open ? 1 : 0)).current;\n  const openRef = useRef(open);\n  openRef.current = open;\n\n  useEffect(() => {\n    let cancelled = false;\n\n    if (open) {\n      setMounted(true);\n      Animated.timing(progress, {\n        toValue: 1,\n        duration,\n        easing: Easing.out(Easing.cubic),\n        useNativeDriver: true,\n      }).start();\n    } else {\n      Animated.timing(progress, {\n        toValue: 0,\n        duration: Math.max(120, duration - 40),\n        easing: Easing.in(Easing.cubic),\n        useNativeDriver: true,\n      }).start(({ finished }) => {\n        // Only unmount if still closed (handles rapid open/close).\n        if (finished && !cancelled && !openRef.current) {\n          setMounted(false);\n        }\n      });\n    }\n\n    return () => {\n      cancelled = true;\n    };\n  }, [open, duration, progress]);\n\n  return { mounted, progress };\n}\n\n/** Overlay fade style from presence progress. */\nexport function overlayStyle(progress: Animated.Value): ViewStyle {\n  return {\n    opacity: progress as unknown as number,\n  };\n}\n\n/** Center dialog: fade + slight scale-up (web dialog enter). */\nexport function dialogContentStyle(progress: Animated.Value): ViewStyle {\n  return {\n    opacity: progress as unknown as number,\n    transform: [\n      {\n        scale: progress.interpolate({\n          inputRange: [0, 1],\n          outputRange: [0.96, 1],\n        }) as unknown as number,\n      },\n    ],\n  };\n}\n\n/** Sheet slide from an edge + fade. */\nexport function sheetContentStyle(\n  progress: Animated.Value,\n  side: \"bottom\" | \"top\" | \"left\" | \"right\",\n): ViewStyle {\n  const distance = 28;\n  const from =\n    side === \"bottom\" || side === \"right\" ? distance : -distance;\n\n  if (side === \"left\" || side === \"right\") {\n    return {\n      opacity: progress as unknown as number,\n      transform: [\n        {\n          translateX: progress.interpolate({\n            inputRange: [0, 1],\n            outputRange: [from, 0],\n          }) as unknown as number,\n        },\n      ],\n    };\n  }\n\n  return {\n    opacity: progress as unknown as number,\n    transform: [\n      {\n        translateY: progress.interpolate({\n          inputRange: [0, 1],\n          outputRange: [from, 0],\n        }) as unknown as number,\n      },\n    ],\n  };\n}\n\n/**\n * Press scale feedback (web button transform on active).\n * Returns animated style + press handlers to merge into Pressable.\n */\nexport function usePressScale(options?: {\n  pressedScale?: number;\n  disabled?: boolean | null;\n}) {\n  const pressedScale = options?.pressedScale ?? 0.97;\n  const scale = useRef(new Animated.Value(1)).current;\n\n  const onPressIn = () => {\n    if (options?.disabled) return;\n    Animated.spring(scale, {\n      toValue: pressedScale,\n      ...springs.snappy,\n    }).start();\n  };\n\n  const onPressOut = () => {\n    Animated.spring(scale, {\n      toValue: 1,\n      ...springs.soft,\n    }).start();\n  };\n\n  const style = {\n    transform: [{ scale }],\n  };\n\n  return { scale, style, onPressIn, onPressOut };\n}\n\n/** Animate a 0–1 value when a boolean toggles (checkbox check, toggle on). */\nexport function useBooleanSpring(\n  on: boolean,\n  config: keyof typeof springs = \"snappy\",\n) {\n  const value = useRef(new Animated.Value(on ? 1 : 0)).current;\n\n  useEffect(() => {\n    Animated.spring(value, {\n      toValue: on ? 1 : 0,\n      ...springs[config],\n    }).start();\n  }, [on, value, config]);\n\n  return value;\n}\n\n/**\n * Animate progress bar fill. Uses JS driver because width % is layout.\n */\nexport function useProgressWidth(pct: number, duration = timings.normal) {\n  const width = useRef(new Animated.Value(pct)).current;\n\n  useEffect(() => {\n    Animated.timing(width, {\n      toValue: pct,\n      duration,\n      easing: Easing.out(Easing.cubic),\n      useNativeDriver: false,\n    }).start();\n  }, [pct, duration, width]);\n\n  return width;\n}\n"
        },
        {
          "path": "packages/ui-native/src/utils/cn.ts",
          "type": "registry:lib",
          "target": "components/ui/native/utils/cn.ts",
          "content": "import type { StyleProp, TextStyle, ViewStyle } from \"react-native\";\n\ntype AnyStyle = ViewStyle | TextStyle;\n\n/**\n * Merge RN styles, filtering falsy entries.\n * Drop-in conceptual counterpart to web `cn()` without Tailwind.\n */\nexport function cn<T extends AnyStyle = ViewStyle>(\n  ...styles: Array<StyleProp<T> | false | null | undefined>\n): StyleProp<T> {\n  return styles.filter(Boolean) as StyleProp<T>;\n}\n"
        },
        {
          "path": "packages/ui-native/src/utils/index.ts",
          "type": "registry:lib",
          "target": "components/ui/native/utils/index.ts",
          "content": "export { cn } from \"./cn\";\nexport { disabledStyle, pressedOpacity } from \"./pressable\";\nexport {\n  springs,\n  timings,\n  springTo,\n  timingTo,\n  usePresence,\n  overlayStyle,\n  dialogContentStyle,\n  sheetContentStyle,\n  usePressScale,\n  useBooleanSpring,\n  useProgressWidth,\n} from \"./animation\";\n"
        },
        {
          "path": "packages/ui-native/src/utils/pressable.ts",
          "type": "registry:lib",
          "target": "components/ui/native/utils/pressable.ts",
          "content": "import type { ViewStyle } from \"react-native\";\n\nexport function disabledStyle(disabled?: boolean): ViewStyle {\n  if (!disabled) return {};\n  return { opacity: 0.5 };\n}\n\nexport function pressedOpacity(pressed: boolean, base = 1): number {\n  return pressed ? Math.max(0.75, base * 0.88) : base;\n}\n"
        }
      ]
    },
    {
      "name": "accordion",
      "type": "registry:ui",
      "title": "Accordion",
      "description": "React Native Accordion for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/accordion.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/accordion.tsx",
          "content": "import {\n  createContext,\n  forwardRef,\n  useContext,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  LayoutAnimation,\n  Platform,\n  Pressable,\n  Text,\n  UIManager,\n  View,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nif (\n  Platform.OS === \"android\" &&\n  UIManager.setLayoutAnimationEnabledExperimental\n) {\n  UIManager.setLayoutAnimationEnabledExperimental(true);\n}\n\ntype AccordionType = \"single\" | \"multiple\";\n\ninterface AccordionContextValue {\n  type: AccordionType;\n  open: string[];\n  toggle: (value: string) => void;\n  collapsible: boolean;\n}\n\nconst AccordionContext = createContext<AccordionContextValue | null>(null);\nconst ItemContext = createContext<string>(\"\");\n\nexport interface AccordionProps extends ViewProps {\n  type?: AccordionType;\n  value?: string | string[];\n  defaultValue?: string | string[];\n  onValueChange?: (value: string | string[]) => void;\n  collapsible?: boolean;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nfunction toArray(v?: string | string[]) {\n  if (v == null) return [];\n  return Array.isArray(v) ? v : [v];\n}\n\nexport const Accordion = forwardRef<View, AccordionProps>(\n  (\n    {\n      type = \"single\",\n      value: valueProp,\n      defaultValue,\n      onValueChange,\n      collapsible = true,\n      children,\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme } = useTheme();\n    const isControlled = valueProp !== undefined;\n    const [internal, setInternal] = useState(toArray(defaultValue));\n    const open = isControlled ? toArray(valueProp) : internal;\n\n    const toggle = (item: string) => {\n      LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);\n      let next: string[];\n      if (type === \"single\") {\n        if (open.includes(item)) {\n          next = collapsible ? [] : open;\n        } else {\n          next = [item];\n        }\n      } else {\n        next = open.includes(item)\n          ? open.filter((v) => v !== item)\n          : [...open, item];\n      }\n      if (!isControlled) setInternal(next);\n      onValueChange?.(type === \"single\" ? (next[0] ?? \"\") : next);\n    };\n\n    return (\n      <AccordionContext.Provider value={{ type, open, toggle, collapsible }}>\n        <View ref={ref} style={cn({ gap: theme.spacing[2] }, style)} {...props}>\n          {children}\n        </View>\n      </AccordionContext.Provider>\n    );\n  },\n);\nAccordion.displayName = \"Accordion\";\n\nexport interface AccordionItemProps extends ViewProps {\n  value: string;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const AccordionItem = forwardRef<View, AccordionItemProps>(\n  ({ value, style, children, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <ItemContext.Provider value={value}>\n        <View\n          ref={ref}\n          style={cn(\n            {\n              borderRadius: theme.radii.xl,\n              borderWidth: 1,\n              borderColor: colors.glassChromeBorder,\n              backgroundColor: colors.glassChromeBgEnv,\n              overflow: \"hidden\",\n            },\n            style,\n          )}\n          {...props}\n        >\n          {children}\n        </View>\n      </ItemContext.Provider>\n    );\n  },\n);\nAccordionItem.displayName = \"AccordionItem\";\n\nexport interface AccordionTriggerProps {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport function AccordionTrigger({ children, style }: AccordionTriggerProps) {\n  const { theme, colors } = useTheme();\n  const ctx = useContext(AccordionContext);\n  const value = useContext(ItemContext);\n  if (!ctx) throw new Error(\"AccordionTrigger must be within Accordion\");\n  const open = ctx.open.includes(value);\n\n  return (\n    <Pressable\n      accessibilityRole=\"button\"\n      accessibilityState={{ expanded: open }}\n      onPress={() => ctx.toggle(value)}\n      style={cn(\n        {\n          flexDirection: \"row\",\n          alignItems: \"center\",\n          justifyContent: \"space-between\",\n          paddingHorizontal: theme.spacing[4],\n          paddingVertical: theme.spacing[3.5],\n        },\n        style,\n      )}\n    >\n      {typeof children === \"string\" ? (\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes.sm,\n            fontWeight: theme.fontWeights.medium,\n            flex: 1,\n          }}\n        >\n          {children}\n        </Text>\n      ) : (\n        children\n      )}\n      <Text style={{ color: colors.mutedForeground, marginLeft: 8 }}>\n        {open ? \"▴\" : \"▾\"}\n      </Text>\n    </Pressable>\n  );\n}\n\nexport interface AccordionContentProps extends ViewProps {\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const AccordionContent = forwardRef<View, AccordionContentProps>(\n  ({ style, children, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    const ctx = useContext(AccordionContext);\n    const value = useContext(ItemContext);\n    if (!ctx || !ctx.open.includes(value)) return null;\n\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            paddingHorizontal: theme.spacing[4],\n            paddingBottom: theme.spacing[4],\n          },\n          style,\n        )}\n        {...props}\n      >\n        {typeof children === \"string\" ? (\n          <Text\n            style={{\n              color: colors.mutedForeground,\n              fontSize: theme.fontSizes.sm,\n              lineHeight: theme.fontSizes.sm * theme.lineHeights.relaxed,\n            }}\n          >\n            {children}\n          </Text>\n        ) : (\n          children\n        )}\n      </View>\n    );\n  },\n);\nAccordionContent.displayName = \"AccordionContent\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "prompt-input",
      "type": "registry:ui",
      "title": "Prompt Input",
      "description": "React Native Prompt Input for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "streaming-text",
      "type": "registry:ui",
      "title": "Streaming Text",
      "description": "React Native Streaming Text for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "typing-indicator",
      "type": "registry:ui",
      "title": "Typing Indicator",
      "description": "React Native Typing Indicator for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "thinking-animation",
      "type": "registry:ui",
      "title": "Thinking Animation",
      "description": "React Native Thinking Animation for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "reasoning-block",
      "type": "registry:ui",
      "title": "Reasoning Block",
      "description": "React Native Reasoning Block for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "citation-card",
      "type": "registry:ui",
      "title": "Citation Card",
      "description": "React Native Citation Card for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "token-counter",
      "type": "registry:ui",
      "title": "Token Counter",
      "description": "React Native Token Counter for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "prompt-suggestions",
      "type": "registry:ui",
      "title": "Prompt Suggestions",
      "description": "React Native Prompt Suggestions for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "agent-card",
      "type": "registry:ui",
      "title": "Agent Card",
      "description": "React Native Agent Card for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "tool-call-viewer",
      "type": "registry:ui",
      "title": "Tool Call Viewer",
      "description": "React Native Tool Call Viewer for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "mcp-server-card",
      "type": "registry:ui",
      "title": "Mcp Server Card",
      "description": "React Native Mcp Server Card for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "ai-model-selector",
      "type": "registry:ui",
      "title": "Ai Model Selector",
      "description": "React Native Ai Model Selector for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "conversation-sidebar",
      "type": "registry:ui",
      "title": "Conversation Sidebar",
      "description": "React Native Conversation Sidebar for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "ai-chat",
      "type": "registry:ui",
      "title": "Ai Chat",
      "description": "React Native Ai Chat for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "floating-widget",
      "type": "registry:ui",
      "title": "Floating Widget",
      "description": "React Native Floating Widget for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge",
        "button",
        "card",
        "progress",
        "skeleton",
        "spinner",
        "textarea"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/ai.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/ai.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\nimport { Skeleton } from \"./skeleton\";\nimport { Spinner } from \"./spinner\";\nimport { Textarea } from \"./textarea\";\n\nexport function PromptInput(props: {\n  value?: string;\n  onChangeText?: (v: string) => void;\n  onSubmit?: () => void;\n}) {\n  return (\n    <View>\n      <Textarea\n        placeholder=\"Ask anything…\"\n        value={props.value}\n        onChangeText={props.onChangeText}\n      />\n      <Button variant=\"primary\" onPress={props.onSubmit} style={{ marginTop: 8 }}>\n        Send\n      </Button>\n    </View>\n  );\n}\n\nexport function StreamingText({ text }: { text: string }) {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.foreground }}>{text}</Text>;\n}\n\nexport function TypingIndicator() {\n  return <Spinner size=\"sm\" />;\n}\n\nexport function ThinkingAnimation() {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: 6, alignItems: \"center\" }}>\n      <Spinner size=\"sm\" />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        Thinking\n      </Text>\n    </View>\n  );\n}\n\nexport function ReasoningBlock({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderLeftWidth: 2,\n        borderLeftColor: colors.primary,\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </View>\n  );\n}\n\nexport function CitationCard({\n  title,\n  source,\n}: {\n  title: string;\n  source?: string;\n}) {\n  return (\n    <Card variant=\"outline\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      {source ? (\n        <CardContent>\n          <Text>{source}</Text>\n        </CardContent>\n      ) : null}\n    </Card>\n  );\n}\n\nexport function TokenCounter({ used = 0, max = 128000 }: { used?: number; max?: number }) {\n  const pct = Math.min(100, Math.round((used / max) * 100));\n  return <Progress value={pct} />;\n}\n\nexport function PromptSuggestions({\n  items,\n  onSelect,\n}: {\n  items: string[];\n  onSelect?: (item: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"outline\" onPress={() => onSelect?.(item)}>\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AgentCard({\n  name,\n  status = \"idle\",\n}: {\n  name: string;\n  status?: string;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant=\"secondary\">{status}</Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ToolCallViewer({\n  name,\n  args,\n}: {\n  name: string;\n  args?: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        padding: theme.spacing[3],\n        borderRadius: theme.radii.lg,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n      }}\n    >\n      <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n        {name}\n      </Text>\n      {args ? (\n        <Text style={{ color: colors.mutedForeground, fontFamily: \"Menlo\" }}>{args}</Text>\n      ) : null}\n    </View>\n  );\n}\n\nexport function McpServerCard({ name, connected }: { name: string; connected?: boolean }) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{name}</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Badge variant={connected ? \"success\" : \"outline\"}>\n          {connected ? \"Connected\" : \"Offline\"}\n        </Badge>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AiModelSelector({\n  value,\n  options,\n  onChange,\n}: {\n  value?: string;\n  options: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function ConversationSidebar({\n  items,\n}: {\n  items: string[];\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[1] }}>\n      {items.map((item) => (\n        <Button key={item} variant=\"ghost\">\n          {item}\n        </Button>\n      ))}\n    </View>\n  );\n}\n\nexport function AiChat({\n  messages,\n}: {\n  messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      {messages.map((m, i) => (\n        <View\n          key={i}\n          style={{\n            alignSelf: m.role === \"user\" ? \"flex-end\" : \"flex-start\",\n            maxWidth: \"85%\",\n            padding: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            backgroundColor:\n              m.role === \"user\" ? colors.primary : colors.glassChromeBgEnv,\n          }}\n        >\n          <Text\n            style={{\n              color: m.role === \"user\" ? colors.primaryForeground : colors.foreground,\n            }}\n          >\n            {m.content}\n          </Text>\n        </View>\n      ))}\n      <PromptInput />\n    </View>\n  );\n}\n\nexport function FloatingWidget({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        right: theme.spacing[4],\n        bottom: theme.spacing[4],\n        borderRadius: theme.radii.full,\n        backgroundColor: colors.primary,\n        padding: theme.spacing[3],\n      }}\n    >\n      {children ?? <Text style={{ color: colors.primaryForeground }}>AI</Text>}\n    </View>\n  );\n}\n\nexport { Skeleton as ThinkingSkeleton };\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "alert-dialog",
      "type": "registry:ui",
      "title": "Alert Dialog",
      "description": "React Native Alert Dialog for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "dialog"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/alert-dialog.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/alert-dialog.tsx",
          "content": "export {\n  Dialog as AlertDialog,\n  DialogTrigger as AlertDialogTrigger,\n  DialogContent as AlertDialogContent,\n  DialogHeader as AlertDialogHeader,\n  DialogFooter as AlertDialogFooter,\n  DialogTitle as AlertDialogTitle,\n  DialogDescription as AlertDialogDescription,\n  DialogClose as AlertDialogCancel,\n} from \"./dialog\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "alert",
      "type": "registry:ui",
      "title": "Alert",
      "description": "React Native Alert for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/alert.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/alert.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  Text,\n  View,\n  type StyleProp,\n  type TextProps,\n  type TextStyle,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type AlertVariant =\n  | \"default\"\n  | \"destructive\"\n  | \"success\"\n  | \"chrome\"\n  | \"outline\";\n\nexport interface AlertProps extends ViewProps {\n  variant?: AlertVariant;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Alert = forwardRef<View, AlertProps>(\n  ({ variant = \"default\", children, style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n\n    const styles: Record<AlertVariant, ViewStyle> = {\n      default: {\n        backgroundColor: \"rgba(26,26,26,0.08)\",\n        borderColor: \"rgba(26,26,26,0.25)\",\n      },\n      destructive: {\n        backgroundColor: \"rgba(180,60,60,0.1)\",\n        borderColor: \"rgba(180,60,60,0.35)\",\n      },\n      success: {\n        backgroundColor: \"rgba(45,138,78,0.1)\",\n        borderColor: \"rgba(45,138,78,0.35)\",\n      },\n      chrome: {\n        backgroundColor: colors.glassChromeBgEnv,\n        borderColor: colors.glassChromeBorder,\n      },\n      outline: {\n        backgroundColor: \"transparent\",\n        borderColor: colors.glassChromeBorder,\n        borderStyle: \"dashed\",\n      },\n    };\n\n    return (\n      <View\n        ref={ref}\n        accessibilityRole=\"alert\"\n        style={cn(\n          {\n            width: \"100%\",\n            borderRadius: theme.radii[\"2xl\"],\n            borderWidth: 1,\n            paddingHorizontal: theme.spacing[4],\n            paddingVertical: theme.spacing[3],\n          },\n          styles[variant],\n          style,\n        )}\n        {...props}\n      >\n        {children}\n      </View>\n    );\n  },\n);\nAlert.displayName = \"Alert\";\n\nexport const AlertTitle = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color: colors.foreground,\n            fontSize: theme.fontSizes.sm,\n            fontWeight: theme.fontWeights.semibold,\n            marginBottom: theme.spacing[1],\n          } satisfies TextStyle,\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nAlertTitle.displayName = \"AlertTitle\";\n\nexport const AlertDescription = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color: colors.glassChromeFgMuted,\n            fontSize: theme.fontSizes.sm,\n            lineHeight: theme.fontSizes.sm * theme.lineHeights.relaxed,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nAlertDescription.displayName = \"AlertDescription\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "avatar",
      "type": "registry:ui",
      "title": "Avatar",
      "description": "React Native Avatar for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/avatar.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/avatar.tsx",
          "content": "import { Image, Text, View, type ImageSourcePropType } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport interface AvatarProps {\n  src?: ImageSourcePropType | string;\n  alt?: string;\n  fallback?: string;\n  size?: number;\n}\n\nexport function Avatar({ src, alt, fallback = \"?\", size = 40 }: AvatarProps) {\n  const { theme, colors } = useTheme();\n  const source =\n    typeof src === \"string\" ? { uri: src } : src;\n  return (\n    <View\n      accessibilityLabel={alt}\n      style={{\n        width: size,\n        height: size,\n        borderRadius: size / 2,\n        overflow: \"hidden\",\n        backgroundColor: colors.glassChromeBgEnv,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        alignItems: \"center\",\n        justifyContent: \"center\",\n      }}\n    >\n      {source ? (\n        <Image source={source} style={{ width: size, height: size }} />\n      ) : (\n        <Text\n          style={{\n            color: colors.glassChromeFg,\n            fontSize: theme.fontSizes.sm,\n            fontWeight: theme.fontWeights.medium,\n          }}\n        >\n          {fallback}\n        </Text>\n      )}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "badge",
      "type": "registry:ui",
      "title": "Badge",
      "description": "React Native Badge for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/badge.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/badge.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  Text,\n  View,\n  type StyleProp,\n  type TextStyle,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type BadgeVariant =\n  | \"default\"\n  | \"secondary\"\n  | \"outline\"\n  | \"destructive\"\n  | \"chrome\"\n  | \"success\";\nexport type BadgeSize = \"sm\" | \"default\" | \"lg\";\n\nexport interface BadgeProps extends ViewProps {\n  variant?: BadgeVariant;\n  size?: BadgeSize;\n  children?: ReactNode;\n  textStyle?: StyleProp<TextStyle>;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Badge = forwardRef<View, BadgeProps>(\n  (\n    {\n      variant = \"default\",\n      size = \"default\",\n      children,\n      textStyle,\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n\n    const padH = size === \"sm\" ? 8 : size === \"lg\" ? 12 : 10;\n    const padV = size === \"lg\" ? 4 : 2;\n    const fontSize =\n      size === \"sm\" ? 10 : size === \"lg\" ? theme.fontSizes.sm : theme.fontSizes.xs;\n\n    const bg: Record<BadgeVariant, string> = {\n      default: \"rgba(26,26,26,0.12)\",\n      secondary: colors.glassChromeBgEnv,\n      outline: \"transparent\",\n      destructive: \"rgba(180,60,60,0.14)\",\n      chrome: colors.glassChromeBgEnv,\n      success: \"rgba(45,138,78,0.16)\",\n    };\n\n    const fg: Record<BadgeVariant, string> = {\n      default: colors.primary,\n      secondary: colors.glassChromeFg,\n      outline: colors.glassChromeFg,\n      destructive: colors.destructive,\n      chrome: colors.glassChromeFg,\n      success: colors.success,\n    };\n\n    const border: Record<BadgeVariant, string> = {\n      default: \"rgba(26,26,26,0.25)\",\n      secondary: colors.glassChromeBorder,\n      outline: colors.glassChromeBorder,\n      destructive: \"rgba(180,60,60,0.35)\",\n      chrome: colors.glassChromeBorder,\n      success: \"rgba(45,138,78,0.35)\",\n    };\n\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            alignSelf: \"flex-start\",\n            flexDirection: \"row\",\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            gap: 4,\n            paddingHorizontal: padH,\n            paddingVertical: padV,\n            borderRadius: theme.radii.full,\n            backgroundColor: bg[variant],\n            borderWidth: 1,\n            borderColor: border[variant],\n          },\n          style,\n        )}\n        {...props}\n      >\n        {typeof children === \"string\" || typeof children === \"number\" ? (\n          <Text\n            style={cn(\n              {\n                color: fg[variant],\n                fontSize,\n                fontWeight: theme.fontWeights.medium,\n              },\n              textStyle,\n            )}\n          >\n            {children}\n          </Text>\n        ) : (\n          children\n        )}\n      </View>\n    );\n  },\n);\nBadge.displayName = \"Badge\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "banner",
      "type": "registry:ui",
      "title": "Banner",
      "description": "React Native Banner for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "alert"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/banner.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/banner.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Alert } from \"./alert\";\n\nexport function Banner({\n  title,\n  children,\n}: {\n  title: string;\n  children?: ReactNode;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Alert variant=\"chrome\">\n      <Text\n        style={{\n          color: colors.foreground,\n          fontWeight: theme.fontWeights.semibold,\n          marginBottom: 4,\n        }}\n      >\n        {title}\n      </Text>\n      {typeof children === \"string\" ? (\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {children}\n        </Text>\n      ) : (\n        children\n      )}\n    </Alert>\n  );\n}\n\nexport function Callout(props: { title: string; children?: ReactNode }) {\n  return <Banner {...props} />;\n}\n\nexport function OfflineBanner() {\n  return <Banner title=\"You’re offline\">Changes will sync when you’re back online.</Banner>;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "callout",
      "type": "registry:ui",
      "title": "Callout",
      "description": "React Native Callout for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "alert"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/banner.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/banner.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Alert } from \"./alert\";\n\nexport function Banner({\n  title,\n  children,\n}: {\n  title: string;\n  children?: ReactNode;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Alert variant=\"chrome\">\n      <Text\n        style={{\n          color: colors.foreground,\n          fontWeight: theme.fontWeights.semibold,\n          marginBottom: 4,\n        }}\n      >\n        {title}\n      </Text>\n      {typeof children === \"string\" ? (\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {children}\n        </Text>\n      ) : (\n        children\n      )}\n    </Alert>\n  );\n}\n\nexport function Callout(props: { title: string; children?: ReactNode }) {\n  return <Banner {...props} />;\n}\n\nexport function OfflineBanner() {\n  return <Banner title=\"You’re offline\">Changes will sync when you’re back online.</Banner>;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "offline-banner",
      "type": "registry:ui",
      "title": "Offline Banner",
      "description": "React Native Offline Banner for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "alert"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/banner.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/banner.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Alert } from \"./alert\";\n\nexport function Banner({\n  title,\n  children,\n}: {\n  title: string;\n  children?: ReactNode;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Alert variant=\"chrome\">\n      <Text\n        style={{\n          color: colors.foreground,\n          fontWeight: theme.fontWeights.semibold,\n          marginBottom: 4,\n        }}\n      >\n        {title}\n      </Text>\n      {typeof children === \"string\" ? (\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {children}\n        </Text>\n      ) : (\n        children\n      )}\n    </Alert>\n  );\n}\n\nexport function Callout(props: { title: string; children?: ReactNode }) {\n  return <Banner {...props} />;\n}\n\nexport function OfflineBanner() {\n  return <Banner title=\"You’re offline\">Changes will sync when you’re back online.</Banner>;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "bottom-navigation",
      "type": "registry:ui",
      "title": "Bottom Navigation",
      "description": "React Native Bottom Navigation for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/bottom-navigation.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/bottom-navigation.tsx",
          "content": "import { Pressable, Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport type BottomNavItem = { key: string; label: string };\n\nexport function BottomNavigation({\n  items,\n  value,\n  onValueChange,\n}: {\n  items: BottomNavItem[];\n  value: string;\n  onValueChange: (key: string) => void;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        flexDirection: \"row\",\n        borderTopWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        backgroundColor: colors.glassChromeBgEnv,\n      }}\n    >\n      {items.map((item) => {\n        const active = item.key === value;\n        return (\n          <Pressable\n            key={item.key}\n            onPress={() => onValueChange(item.key)}\n            style={{\n              flex: 1,\n              paddingVertical: theme.spacing[3],\n              alignItems: \"center\",\n            }}\n          >\n            <Text\n              style={{\n                color: active ? colors.primary : colors.mutedForeground,\n                fontSize: theme.fontSizes.xs,\n                fontWeight: theme.fontWeights.medium,\n              }}\n            >\n              {item.label}\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function Dock({\n  items,\n  value,\n  onValueChange,\n}: {\n  items: BottomNavItem[];\n  value: string;\n  onValueChange: (key: string) => void;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        flexDirection: \"row\",\n        alignSelf: \"center\",\n        gap: theme.spacing[1],\n        padding: theme.spacing[1],\n        borderRadius: theme.radii.full,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        backgroundColor: colors.glassChromeBgEnv,\n      }}\n    >\n      {items.map((item) => {\n        const active = item.key === value;\n        return (\n          <Pressable\n            key={item.key}\n            onPress={() => onValueChange(item.key)}\n            style={{\n              paddingHorizontal: theme.spacing[3],\n              paddingVertical: theme.spacing[2],\n              borderRadius: theme.radii.full,\n              backgroundColor: active ? colors.primary : \"transparent\",\n            }}\n          >\n            <Text\n              style={{\n                color: active ? colors.primaryForeground : colors.glassChromeFg,\n                fontSize: theme.fontSizes.xs,\n              }}\n            >\n              {item.label}\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function NavigationMenu(props: {\n  items: BottomNavItem[];\n  value: string;\n  onValueChange: (key: string) => void;\n}) {\n  return <Dock {...props} />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "dock",
      "type": "registry:ui",
      "title": "Dock",
      "description": "React Native Dock for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/bottom-navigation.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/bottom-navigation.tsx",
          "content": "import { Pressable, Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport type BottomNavItem = { key: string; label: string };\n\nexport function BottomNavigation({\n  items,\n  value,\n  onValueChange,\n}: {\n  items: BottomNavItem[];\n  value: string;\n  onValueChange: (key: string) => void;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        flexDirection: \"row\",\n        borderTopWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        backgroundColor: colors.glassChromeBgEnv,\n      }}\n    >\n      {items.map((item) => {\n        const active = item.key === value;\n        return (\n          <Pressable\n            key={item.key}\n            onPress={() => onValueChange(item.key)}\n            style={{\n              flex: 1,\n              paddingVertical: theme.spacing[3],\n              alignItems: \"center\",\n            }}\n          >\n            <Text\n              style={{\n                color: active ? colors.primary : colors.mutedForeground,\n                fontSize: theme.fontSizes.xs,\n                fontWeight: theme.fontWeights.medium,\n              }}\n            >\n              {item.label}\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function Dock({\n  items,\n  value,\n  onValueChange,\n}: {\n  items: BottomNavItem[];\n  value: string;\n  onValueChange: (key: string) => void;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        flexDirection: \"row\",\n        alignSelf: \"center\",\n        gap: theme.spacing[1],\n        padding: theme.spacing[1],\n        borderRadius: theme.radii.full,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        backgroundColor: colors.glassChromeBgEnv,\n      }}\n    >\n      {items.map((item) => {\n        const active = item.key === value;\n        return (\n          <Pressable\n            key={item.key}\n            onPress={() => onValueChange(item.key)}\n            style={{\n              paddingHorizontal: theme.spacing[3],\n              paddingVertical: theme.spacing[2],\n              borderRadius: theme.radii.full,\n              backgroundColor: active ? colors.primary : \"transparent\",\n            }}\n          >\n            <Text\n              style={{\n                color: active ? colors.primaryForeground : colors.glassChromeFg,\n                fontSize: theme.fontSizes.xs,\n              }}\n            >\n              {item.label}\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function NavigationMenu(props: {\n  items: BottomNavItem[];\n  value: string;\n  onValueChange: (key: string) => void;\n}) {\n  return <Dock {...props} />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "navigation-menu",
      "type": "registry:ui",
      "title": "Navigation Menu",
      "description": "React Native Navigation Menu for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/bottom-navigation.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/bottom-navigation.tsx",
          "content": "import { Pressable, Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport type BottomNavItem = { key: string; label: string };\n\nexport function BottomNavigation({\n  items,\n  value,\n  onValueChange,\n}: {\n  items: BottomNavItem[];\n  value: string;\n  onValueChange: (key: string) => void;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        flexDirection: \"row\",\n        borderTopWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        backgroundColor: colors.glassChromeBgEnv,\n      }}\n    >\n      {items.map((item) => {\n        const active = item.key === value;\n        return (\n          <Pressable\n            key={item.key}\n            onPress={() => onValueChange(item.key)}\n            style={{\n              flex: 1,\n              paddingVertical: theme.spacing[3],\n              alignItems: \"center\",\n            }}\n          >\n            <Text\n              style={{\n                color: active ? colors.primary : colors.mutedForeground,\n                fontSize: theme.fontSizes.xs,\n                fontWeight: theme.fontWeights.medium,\n              }}\n            >\n              {item.label}\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function Dock({\n  items,\n  value,\n  onValueChange,\n}: {\n  items: BottomNavItem[];\n  value: string;\n  onValueChange: (key: string) => void;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        flexDirection: \"row\",\n        alignSelf: \"center\",\n        gap: theme.spacing[1],\n        padding: theme.spacing[1],\n        borderRadius: theme.radii.full,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        backgroundColor: colors.glassChromeBgEnv,\n      }}\n    >\n      {items.map((item) => {\n        const active = item.key === value;\n        return (\n          <Pressable\n            key={item.key}\n            onPress={() => onValueChange(item.key)}\n            style={{\n              paddingHorizontal: theme.spacing[3],\n              paddingVertical: theme.spacing[2],\n              borderRadius: theme.radii.full,\n              backgroundColor: active ? colors.primary : \"transparent\",\n            }}\n          >\n            <Text\n              style={{\n                color: active ? colors.primaryForeground : colors.glassChromeFg,\n                fontSize: theme.fontSizes.xs,\n              }}\n            >\n              {item.label}\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function NavigationMenu(props: {\n  items: BottomNavItem[];\n  value: string;\n  onValueChange: (key: string) => void;\n}) {\n  return <Dock {...props} />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "breadcrumb",
      "type": "registry:ui",
      "title": "Breadcrumb",
      "description": "React Native Breadcrumb for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/breadcrumb.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/breadcrumb.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport function Breadcrumb({ children }: { children?: ReactNode }) {\n  const { theme } = useTheme();\n  return (\n    <View\n      style={{\n        flexDirection: \"row\",\n        flexWrap: \"wrap\",\n        alignItems: \"center\",\n        gap: theme.spacing[1],\n      }}\n    >\n      {children}\n    </View>\n  );\n}\n\nexport function BreadcrumbItem({ children }: { children?: ReactNode }) {\n  return <View>{children}</View>;\n}\n\nexport function BreadcrumbSeparator() {\n  const { colors } = useTheme();\n  return <Text style={{ color: colors.mutedForeground }}>/</Text>;\n}\n\nexport function BreadcrumbPage({ children }: { children?: ReactNode }) {\n  const { colors, theme } = useTheme();\n  return (\n    <Text\n      style={{\n        color: colors.foreground,\n        fontSize: theme.fontSizes.sm,\n        fontWeight: theme.fontWeights.medium,\n      }}\n    >\n      {children}\n    </Text>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "button",
      "type": "registry:ui",
      "title": "Button",
      "description": "React Native Button for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/button.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/button.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  ActivityIndicator,\n  Animated,\n  Pressable,\n  Text,\n  type PressableProps,\n  type StyleProp,\n  type TextStyle,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { usePressScale } from \"../utils/animation\";\nimport { cn } from \"../utils/cn\";\nimport { disabledStyle, pressedOpacity } from \"../utils/pressable\";\n\nexport type ButtonVariant =\n  | \"default\"\n  | \"primary\"\n  | \"destructive\"\n  | \"outline\"\n  | \"secondary\"\n  | \"ghost\"\n  | \"glass\"\n  | \"link\";\nexport type ButtonSize = \"default\" | \"sm\" | \"lg\" | \"icon\";\nexport type ButtonShape = \"rounded\" | \"pill\" | \"rectangular\";\n\nexport interface ButtonProps extends Omit<PressableProps, \"children\"> {\n  variant?: ButtonVariant;\n  size?: ButtonSize;\n  shape?: ButtonShape;\n  loading?: boolean;\n  children?: ReactNode;\n  textStyle?: StyleProp<TextStyle>;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Button = forwardRef<React.ElementRef<typeof Pressable>, ButtonProps>(\n  (\n    {\n      variant = \"default\",\n      size = \"default\",\n      shape = \"rounded\",\n      loading = false,\n      disabled,\n      children,\n      textStyle,\n      style,\n      onPressIn,\n      onPressOut,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const isDisabled = disabled || loading;\n    const press = usePressScale({\n      pressedScale: variant === \"link\" ? 1 : 0.97,\n      disabled: isDisabled,\n    });\n\n    const height =\n      size === \"sm\" ? 36 : size === \"lg\" ? 48 : size === \"icon\" ? 40 : 40;\n    const padH =\n      size === \"sm\" ? 16 : size === \"lg\" ? 32 : size === \"icon\" ? 0 : 20;\n    const fontSize =\n      size === \"sm\" ? theme.fontSizes.xs : size === \"lg\" ? theme.fontSizes.base : theme.fontSizes.sm;\n\n    const radius =\n      shape === \"pill\"\n        ? theme.radii.full\n        : shape === \"rectangular\"\n          ? size === \"sm\"\n            ? theme.radii.sm\n            : size === \"lg\"\n              ? theme.radii.lg\n              : theme.radii.md\n          : theme.radii.xl;\n\n    const bg: Record<ButtonVariant, string> = {\n      default: colors.glassButtonUiBg,\n      primary: colors.primary,\n      destructive: colors.destructive,\n      outline: colors.glassChromeBgEnv,\n      secondary: colors.glassSurfaceFill,\n      ghost: \"transparent\",\n      glass: colors.glassButtonUiBg,\n      link: \"transparent\",\n    };\n\n    const fg: Record<ButtonVariant, string> = {\n      default: colors.glassButtonUiFg,\n      primary: colors.primaryForeground,\n      destructive: colors.destructiveForeground,\n      outline: colors.glassChromeFg,\n      secondary: colors.glassChromeFg,\n      ghost: colors.foreground,\n      glass: colors.glassButtonUiFg,\n      link: colors.primary,\n    };\n\n    const borderColor: Record<ButtonVariant, string> = {\n      default: colors.glassButtonUiBorder,\n      primary: \"transparent\",\n      destructive: \"transparent\",\n      outline: colors.glassChromeBorder,\n      secondary: colors.glassChromeBorder,\n      ghost: \"transparent\",\n      glass: colors.glassButtonUiBorder,\n      link: \"transparent\",\n    };\n\n    return (\n      <Animated.View style={press.style}>\n        <Pressable\n          ref={ref}\n          accessibilityRole=\"button\"\n          accessibilityState={{ disabled: !!isDisabled, busy: !!loading }}\n          disabled={isDisabled}\n          onPressIn={(e) => {\n            press.onPressIn();\n            onPressIn?.(e);\n          }}\n          onPressOut={(e) => {\n            press.onPressOut();\n            onPressOut?.(e);\n          }}\n          style={({ pressed }) =>\n            cn(\n              {\n                height,\n                minWidth: size === \"icon\" ? height : undefined,\n                width: size === \"icon\" ? height : undefined,\n                paddingHorizontal: padH,\n                borderRadius: radius,\n                backgroundColor: bg[variant],\n                borderWidth: variant === \"link\" || variant === \"ghost\" ? 0 : 1,\n                borderColor: borderColor[variant],\n                flexDirection: \"row\",\n                alignItems: \"center\",\n                justifyContent: \"center\",\n                gap: 8,\n                opacity: pressedOpacity(pressed) * (isDisabled ? 0.5 : 1),\n              } satisfies ViewStyle,\n              disabledStyle(isDisabled),\n              style,\n            )\n          }\n          {...props}\n        >\n          {loading ? (\n            <ActivityIndicator color={fg[variant]} size=\"small\" />\n          ) : typeof children === \"string\" || typeof children === \"number\" ? (\n            <Text\n              style={cn(\n                {\n                  color: fg[variant],\n                  fontSize,\n                  fontWeight: theme.fontWeights.semibold,\n                  textDecorationLine: variant === \"link\" ? \"underline\" : \"none\",\n                } satisfies TextStyle,\n                textStyle,\n              )}\n            >\n              {children}\n            </Text>\n          ) : (\n            children\n          )}\n        </Pressable>\n      </Animated.View>\n    );\n  },\n);\nButton.displayName = \"Button\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "calendar",
      "type": "registry:ui",
      "title": "Calendar",
      "description": "React Native Calendar for Expo, iOS, and Android.",
      "dependencies": [
        "date-fns"
      ],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/calendar.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/calendar.tsx",
          "content": "import { useMemo, useState } from \"react\";\nimport {\n  Pressable,\n  Text,\n  View,\n  type StyleProp,\n  type ViewStyle,\n} from \"react-native\";\nimport {\n  addMonths,\n  eachDayOfInterval,\n  endOfMonth,\n  endOfWeek,\n  format,\n  isSameDay,\n  isSameMonth,\n  isToday,\n  startOfMonth,\n  startOfWeek,\n  subMonths,\n} from \"date-fns\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport interface DateRange {\n  from?: Date;\n  to?: Date;\n}\n\nexport type CalendarMode = \"single\" | \"range\";\n\nexport interface CalendarProps {\n  mode?: CalendarMode;\n  selected?: Date | DateRange;\n  onSelect?: (value: Date | DateRange | undefined) => void;\n  month?: Date;\n  onMonthChange?: (month: Date) => void;\n  disabled?: (date: Date) => boolean;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport function Calendar({\n  mode = \"single\",\n  selected,\n  onSelect,\n  month: monthProp,\n  onMonthChange,\n  disabled,\n  style,\n}: CalendarProps) {\n  const { theme, colors } = useTheme();\n  const [internalMonth, setInternalMonth] = useState(new Date());\n  const month = monthProp ?? internalMonth;\n\n  const setMonth = (m: Date) => {\n    if (!monthProp) setInternalMonth(m);\n    onMonthChange?.(m);\n  };\n\n  const days = useMemo(() => {\n    const start = startOfWeek(startOfMonth(month), { weekStartsOn: 0 });\n    const end = endOfWeek(endOfMonth(month), { weekStartsOn: 0 });\n    return eachDayOfInterval({ start, end });\n  }, [month]);\n\n  const weekDays = [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"];\n\n  const isSelected = (day: Date) => {\n    if (mode === \"single\" && selected instanceof Date) {\n      return isSameDay(day, selected);\n    }\n    if (mode === \"range\" && selected && !(selected instanceof Date)) {\n      if (selected.from && isSameDay(day, selected.from)) return true;\n      if (selected.to && isSameDay(day, selected.to)) return true;\n    }\n    return false;\n  };\n\n  const isInRange = (day: Date) => {\n    if (mode !== \"range\" || !selected || selected instanceof Date) return false;\n    if (!selected.from || !selected.to) return false;\n    return day >= selected.from && day <= selected.to;\n  };\n\n  const handleSelect = (day: Date) => {\n    if (disabled?.(day)) return;\n    if (mode === \"single\") {\n      onSelect?.(day);\n      return;\n    }\n    const range = (selected && !(selected instanceof Date)\n      ? selected\n      : {}) as DateRange;\n    if (!range.from || (range.from && range.to)) {\n      onSelect?.({ from: day, to: undefined });\n    } else if (day < range.from) {\n      onSelect?.({ from: day, to: range.from });\n    } else {\n      onSelect?.({ from: range.from, to: day });\n    }\n  };\n\n  return (\n    <View\n      style={cn(\n        {\n          padding: theme.spacing[3],\n          borderRadius: theme.radii[\"2xl\"],\n          backgroundColor: colors.glassChromeBgEnv,\n          borderWidth: 1,\n          borderColor: colors.glassChromeBorder,\n          width: 320,\n        },\n        style,\n      )}\n    >\n      <View\n        style={{\n          flexDirection: \"row\",\n          alignItems: \"center\",\n          justifyContent: \"space-between\",\n          marginBottom: theme.spacing[3],\n        }}\n      >\n        <Pressable\n          onPress={() => setMonth(subMonths(month, 1))}\n          accessibilityLabel=\"Previous month\"\n          style={{\n            width: 36,\n            height: 36,\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            borderRadius: theme.radii.lg,\n          }}\n        >\n          <Text style={{ color: colors.foreground, fontSize: 18 }}>‹</Text>\n        </Pressable>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontWeight: theme.fontWeights.semibold,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {format(month, \"MMMM yyyy\")}\n        </Text>\n        <Pressable\n          onPress={() => setMonth(addMonths(month, 1))}\n          accessibilityLabel=\"Next month\"\n          style={{\n            width: 36,\n            height: 36,\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            borderRadius: theme.radii.lg,\n          }}\n        >\n          <Text style={{ color: colors.foreground, fontSize: 18 }}>›</Text>\n        </Pressable>\n      </View>\n\n      <View style={{ flexDirection: \"row\", marginBottom: theme.spacing[1] }}>\n        {weekDays.map((d) => (\n          <View key={d} style={{ flex: 1, alignItems: \"center\", paddingVertical: 4 }}>\n            <Text\n              style={{\n                color: colors.mutedForeground,\n                fontSize: theme.fontSizes.xs,\n                fontWeight: theme.fontWeights.medium,\n              }}\n            >\n              {d}\n            </Text>\n          </View>\n        ))}\n      </View>\n\n      <View style={{ flexDirection: \"row\", flexWrap: \"wrap\" }}>\n        {days.map((day) => {\n          const outside = !isSameMonth(day, month);\n          const selectedDay = isSelected(day);\n          const inRange = isInRange(day);\n          const today = isToday(day);\n          const isDisabled = disabled?.(day);\n\n          return (\n            <Pressable\n              key={day.toISOString()}\n              disabled={isDisabled}\n              onPress={() => handleSelect(day)}\n              style={{\n                width: `${100 / 7}%`,\n                aspectRatio: 1,\n                alignItems: \"center\",\n                justifyContent: \"center\",\n                backgroundColor: selectedDay\n                  ? colors.primary\n                  : inRange\n                    ? \"rgba(128,128,128,0.15)\"\n                    : \"transparent\",\n                borderRadius: theme.radii.lg,\n                opacity: outside ? 0.35 : isDisabled ? 0.35 : 1,\n                borderWidth: today && !selectedDay ? 1 : 0,\n                borderColor: colors.ring,\n              }}\n            >\n              <Text\n                style={{\n                  color: selectedDay\n                    ? colors.primaryForeground\n                    : colors.foreground,\n                  fontSize: theme.fontSizes.sm,\n                  fontWeight: selectedDay\n                    ? theme.fontWeights.semibold\n                    : theme.fontWeights.normal,\n                }}\n              >\n                {format(day, \"d\")}\n              </Text>\n            </Pressable>\n          );\n        })}\n      </View>\n    </View>\n  );\n}\n\nexport function CalendarDayButton() {\n  return null;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "card",
      "type": "registry:ui",
      "title": "Card",
      "description": "React Native Card for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "glass-surface"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/card.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/card.tsx",
          "content": "import { createContext, forwardRef, useContext, type ReactNode } from \"react\";\nimport {\n  Text,\n  View,\n  type StyleProp,\n  type TextProps,\n  type TextStyle,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\nimport { GlassSurface } from \"./glass-surface\";\n\nexport type CardVariant = \"chrome\" | \"elevated\" | \"content\" | \"outline\";\n\ninterface CardContextValue {\n  variant: CardVariant;\n}\n\nconst CardContext = createContext<CardContextValue>({ variant: \"chrome\" });\n\nexport interface CardProps extends ViewProps {\n  variant?: CardVariant;\n  gradient?: string;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Card = forwardRef<View, CardProps>(\n  ({ variant = \"chrome\", gradient, children, style, ...props }, ref) => {\n    return (\n      <CardContext.Provider value={{ variant }}>\n        <GlassSurface\n          ref={ref}\n          variant={variant === \"elevated\" ? \"elevated\" : variant}\n          contentBackground={gradient}\n          style={cn({ overflow: \"hidden\" }, style)}\n          {...props}\n        >\n          {children}\n        </GlassSurface>\n      </CardContext.Provider>\n    );\n  },\n);\nCard.displayName = \"Card\";\n\nexport const CardHeader = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flexDirection: \"column\",\n            gap: theme.spacing[1.5],\n            padding: theme.spacing[6],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nCardHeader.displayName = \"CardHeader\";\n\nexport const CardTitle = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    const { variant } = useContext(CardContext);\n    const color =\n      variant === \"content\" ? colors.contentText : colors.foreground;\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color,\n            fontSize: theme.fontSizes.lg,\n            fontWeight: theme.fontWeights.semibold,\n            letterSpacing: -0.2,\n          } satisfies TextStyle,\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nCardTitle.displayName = \"CardTitle\";\n\nexport const CardDescription = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    const { variant } = useContext(CardContext);\n    const color =\n      variant === \"content\" ? colors.contentTextMuted : colors.mutedForeground;\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color,\n            fontSize: theme.fontSizes.sm,\n            lineHeight: theme.fontSizes.sm * theme.lineHeights.normal,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nCardDescription.displayName = \"CardDescription\";\n\nexport const CardContent = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            paddingHorizontal: theme.spacing[6],\n            paddingBottom: theme.spacing[6],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nCardContent.displayName = \"CardContent\";\n\nexport const CardFooter = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flexDirection: \"row\",\n            alignItems: \"center\",\n            paddingHorizontal: theme.spacing[6],\n            paddingBottom: theme.spacing[6],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nCardFooter.displayName = \"CardFooter\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "carousel",
      "type": "registry:ui",
      "title": "Carousel",
      "description": "React Native Carousel for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/carousel.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/carousel.tsx",
          "content": "import {\n  createContext,\n  useCallback,\n  useContext,\n  useEffect,\n  useRef,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  Dimensions,\n  FlatList,\n  Pressable,\n  Text,\n  View,\n  type ListRenderItemInfo,\n  type NativeScrollEvent,\n  type NativeSyntheticEvent,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n  type ViewToken,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\ninterface CarouselContextValue {\n  index: number;\n  setIndex: (i: number) => void;\n  scrollTo: (i: number) => void;\n  count: number;\n  setCount: (n: number) => void;\n  itemWidth: number;\n}\n\nconst CarouselContext = createContext<CarouselContextValue | null>(null);\n\nfunction useCarousel() {\n  const ctx = useContext(CarouselContext);\n  if (!ctx) throw new Error(\"Carousel components must be used within Carousel\");\n  return ctx;\n}\n\nexport interface CarouselProps extends ViewProps {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n  itemWidth?: number;\n}\n\nexport function Carousel({\n  children,\n  style,\n  itemWidth = Dimensions.get(\"window\").width - 48,\n  ...props\n}: CarouselProps) {\n  const [index, setIndex] = useState(0);\n  const [count, setCount] = useState(0);\n  const listRef = useRef<FlatList>(null);\n\n  const scrollTo = useCallback(\n    (i: number) => {\n      listRef.current?.scrollToIndex({ index: i, animated: true });\n      setIndex(i);\n    },\n    [],\n  );\n\n  return (\n    <CarouselContext.Provider\n      value={{ index, setIndex, scrollTo, count, setCount, itemWidth }}\n    >\n      <View style={cn({ position: \"relative\" }, style)} {...props}>\n        {/* inject list ref via CarouselContent */}\n        <CarouselListBridge listRef={listRef}>{children}</CarouselListBridge>\n      </View>\n    </CarouselContext.Provider>\n  );\n}\n\nconst ListRefContext = createContext<React.RefObject<FlatList | null> | null>(\n  null,\n);\n\nfunction CarouselListBridge({\n  listRef,\n  children,\n}: {\n  listRef: React.RefObject<FlatList | null>;\n  children?: ReactNode;\n}) {\n  return (\n    <ListRefContext.Provider value={listRef}>{children}</ListRefContext.Provider>\n  );\n}\n\nexport interface CarouselContentProps {\n  data?: ReactNode[];\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Pass either `data` as an array of slides, or children (each child = one slide).\n */\nexport function CarouselContent({ data, children, style }: CarouselContentProps) {\n  const ctx = useCarousel();\n  const listRef = useContext(ListRefContext);\n  const slides =\n    data ??\n    (Array.isArray(children) ? children : children != null ? [children] : []);\n\n  const { setCount } = ctx;\n  useEffect(() => {\n    setCount(slides.length);\n  }, [slides.length, setCount]);\n\n  const onViewableItemsChanged = useRef(\n    ({ viewableItems }: { viewableItems: ViewToken[] }) => {\n      const first = viewableItems[0];\n      if (first?.index != null) ctx.setIndex(first.index);\n    },\n  ).current;\n\n  return (\n    <FlatList\n      ref={listRef}\n      horizontal\n      pagingEnabled\n      showsHorizontalScrollIndicator={false}\n      data={slides}\n      keyExtractor={(_, i) => String(i)}\n      style={style}\n      snapToInterval={ctx.itemWidth}\n      decelerationRate=\"fast\"\n      onMomentumScrollEnd={(e: NativeSyntheticEvent<NativeScrollEvent>) => {\n        const i = Math.round(\n          e.nativeEvent.contentOffset.x / Math.max(1, ctx.itemWidth),\n        );\n        ctx.setIndex(i);\n      }}\n      onViewableItemsChanged={onViewableItemsChanged}\n      viewabilityConfig={{ itemVisiblePercentThreshold: 60 }}\n      renderItem={({ item }: ListRenderItemInfo<ReactNode>) => (\n        <View style={{ width: ctx.itemWidth }}>{item}</View>\n      )}\n      getItemLayout={(_, index) => ({\n        length: ctx.itemWidth,\n        offset: ctx.itemWidth * index,\n        index,\n      })}\n    />\n  );\n}\n\nexport function CarouselItem({\n  children,\n  style,\n}: {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}) {\n  const ctx = useCarousel();\n  return <View style={cn({ width: ctx.itemWidth }, style)}>{children}</View>;\n}\n\nexport function CarouselPrevious({\n  style,\n}: {\n  style?: StyleProp<ViewStyle>;\n}) {\n  const { theme, colors } = useTheme();\n  const ctx = useCarousel();\n  const disabled = ctx.index <= 0;\n  return (\n    <Pressable\n      accessibilityRole=\"button\"\n      accessibilityLabel=\"Previous slide\"\n      disabled={disabled}\n      onPress={() => ctx.scrollTo(Math.max(0, ctx.index - 1))}\n      style={cn(\n        {\n          position: \"absolute\",\n          left: 8,\n          top: \"45%\",\n          width: 36,\n          height: 36,\n          borderRadius: theme.radii.full,\n          backgroundColor: colors.glassChromeBgEnv,\n          borderWidth: 1,\n          borderColor: colors.glassChromeBorder,\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          opacity: disabled ? 0.4 : 1,\n          zIndex: 2,\n        },\n        style,\n      )}\n    >\n      <Text style={{ color: colors.foreground }}>‹</Text>\n    </Pressable>\n  );\n}\n\nexport function CarouselNext({ style }: { style?: StyleProp<ViewStyle> }) {\n  const { theme, colors } = useTheme();\n  const ctx = useCarousel();\n  const disabled = ctx.index >= ctx.count - 1;\n  return (\n    <Pressable\n      accessibilityRole=\"button\"\n      accessibilityLabel=\"Next slide\"\n      disabled={disabled}\n      onPress={() =>\n        ctx.scrollTo(Math.min(ctx.count - 1, ctx.index + 1))\n      }\n      style={cn(\n        {\n          position: \"absolute\",\n          right: 8,\n          top: \"45%\",\n          width: 36,\n          height: 36,\n          borderRadius: theme.radii.full,\n          backgroundColor: colors.glassChromeBgEnv,\n          borderWidth: 1,\n          borderColor: colors.glassChromeBorder,\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          opacity: disabled ? 0.4 : 1,\n          zIndex: 2,\n        },\n        style,\n      )}\n    >\n      <Text style={{ color: colors.foreground }}>›</Text>\n    </Pressable>\n  );\n}\n\nexport type CarouselApi = {\n  index: number;\n  scrollTo: (i: number) => void;\n  count: number;\n};\n\nexport function useCarouselApi(): CarouselApi {\n  const ctx = useCarousel();\n  return { index: ctx.index, scrollTo: ctx.scrollTo, count: ctx.count };\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "bar-chart",
      "type": "registry:ui",
      "title": "Bar Chart",
      "description": "React Native Bar Chart for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "line-chart",
      "type": "registry:ui",
      "title": "Line Chart",
      "description": "React Native Line Chart for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "area-chart",
      "type": "registry:ui",
      "title": "Area Chart",
      "description": "React Native Area Chart for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "sparkline",
      "type": "registry:ui",
      "title": "Sparkline",
      "description": "React Native Sparkline for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "stacked-bar-chart",
      "type": "registry:ui",
      "title": "Stacked Bar Chart",
      "description": "React Native Stacked Bar Chart for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "pie-chart",
      "type": "registry:ui",
      "title": "Pie Chart",
      "description": "React Native Pie Chart for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "donut-chart",
      "type": "registry:ui",
      "title": "Donut Chart",
      "description": "React Native Donut Chart for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "radar-chart",
      "type": "registry:ui",
      "title": "Radar Chart",
      "description": "React Native Radar Chart for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "funnel-chart",
      "type": "registry:ui",
      "title": "Funnel Chart",
      "description": "React Native Funnel Chart for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "heatmap",
      "type": "registry:ui",
      "title": "Heatmap",
      "description": "React Native Heatmap for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "tree-map",
      "type": "registry:ui",
      "title": "Tree Map",
      "description": "React Native Tree Map for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "sankey",
      "type": "registry:ui",
      "title": "Sankey",
      "description": "React Native Sankey for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "gauge",
      "type": "registry:ui",
      "title": "Gauge",
      "description": "React Native Gauge for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "metric-card",
      "type": "registry:ui",
      "title": "Metric Card",
      "description": "React Native Metric Card for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "chart-frame",
      "type": "registry:ui",
      "title": "Chart Frame",
      "description": "React Native Chart Frame for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "chart-period",
      "type": "registry:ui",
      "title": "Chart Period",
      "description": "React Native Chart Period for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/charts.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/charts.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Progress } from \"./progress\";\n\nfunction ChartShell({\n  title,\n  children,\n}: {\n  title: string;\n  children: ReactNode;\n}) {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n      </CardHeader>\n      <CardContent>{children}</CardContent>\n    </Card>\n  );\n}\n\nfunction Bars({ values }: { values: number[] }) {\n  const { colors, theme } = useTheme();\n  const max = Math.max(...values, 1);\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"flex-end\", gap: 6, height: 96 }}>\n      {values.map((v, i) => (\n        <View\n          key={i}\n          style={{\n            flex: 1,\n            height: Math.max(8, Math.round((v / max) * 96)),\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.35 + (v / max) * 0.65,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function BarChart({ data = [12, 28, 18, 36, 22] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Bar\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function LineChart({ data = [8, 14, 11, 20, 18, 26] }: { data?: number[] }) {\n  return (\n    <ChartShell title=\"Line\">\n      <Bars values={data} />\n    </ChartShell>\n  );\n}\n\nexport function AreaChart(props: { data?: number[] }) {\n  return <LineChart {...props} />;\n}\n\nexport function Sparkline({ data = [4, 8, 6, 10, 7] }: { data?: number[] }) {\n  return <Bars values={data} />;\n}\n\nexport function StackedBarChart({ data = [10, 16, 12, 20] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function PieChart({ value = 62 }: { value?: number }) {\n  return (\n    <ChartShell title=\"Pie\">\n      <Progress value={value} />\n      <Text style={{ marginTop: 8 }}>{value}%</Text>\n    </ChartShell>\n  );\n}\n\nexport function DonutChart(props: { value?: number }) {\n  return <PieChart {...props} />;\n}\n\nexport function RadarChart({ data = [12, 20, 16, 24, 18] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function FunnelChart({ data = [40, 28, 18, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Heatmap({ cells = 16 }: { cells?: number }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: 4 }}>\n      {Array.from({ length: cells }, (_, i) => (\n        <View\n          key={i}\n          style={{\n            width: 18,\n            height: 18,\n            borderRadius: theme.radii.sm,\n            backgroundColor: colors.primary,\n            opacity: 0.15 + (i % 5) * 0.15,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function TreeMap({ data = [30, 20, 15, 10] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Sankey({ data = [24, 18, 12] }: { data?: number[] }) {\n  return <BarChart data={data} />;\n}\n\nexport function Gauge({ value = 72 }: { value?: number }) {\n  return <DonutChart value={value} />;\n}\n\nexport function MetricCard({\n  label,\n  value,\n}: {\n  label: string;\n  value: string;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardContent>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n          {label}\n        </Text>\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes[\"2xl\"] ?? 24,\n            fontWeight: theme.fontWeights.semibold,\n          }}\n        >\n          {value}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function ChartFrame({ children }: { children?: ReactNode }) {\n  return <Card variant=\"chrome\">{children}</Card>;\n}\n\nexport function ChartPeriod({\n  value,\n  options = [\"7d\", \"30d\", \"90d\"],\n}: {\n  value?: string;\n  options?: string[];\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Text\n          key={o}\n          style={{\n            color: o === value ? colors.primary : colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          }}\n        >\n          {o}\n        </Text>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "checkbox",
      "type": "registry:ui",
      "title": "Checkbox",
      "description": "React Native Checkbox for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/checkbox.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/checkbox.tsx",
          "content": "import { forwardRef, useState } from \"react\";\nimport {\n  Animated,\n  Pressable,\n  Text,\n  type PressableProps,\n  type StyleProp,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { useBooleanSpring, usePressScale } from \"../utils/animation\";\nimport { cn } from \"../utils/cn\";\n\nexport type CheckboxVariant = \"chrome\" | \"outline\";\nexport type CheckboxSize = \"sm\" | \"default\" | \"lg\";\nexport type CheckedState = boolean | \"indeterminate\";\n\nexport interface CheckboxProps extends Omit<PressableProps, \"onPress\"> {\n  checked?: CheckedState;\n  defaultChecked?: boolean;\n  onCheckedChange?: (checked: boolean) => void;\n  variant?: CheckboxVariant;\n  size?: CheckboxSize;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Checkbox = forwardRef<\n  React.ElementRef<typeof Pressable>,\n  CheckboxProps\n>(\n  (\n    {\n      checked: checkedProp,\n      defaultChecked = false,\n      onCheckedChange,\n      variant = \"chrome\",\n      size = \"default\",\n      disabled,\n      style,\n      onPressIn,\n      onPressOut,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const isControlled = checkedProp !== undefined;\n    const [internal, setInternal] = useState(defaultChecked);\n    const checked = isControlled ? checkedProp : internal;\n    const isOn = checked === true || checked === \"indeterminate\";\n    const checkAnim = useBooleanSpring(isOn, \"snappy\");\n    const press = usePressScale({ pressedScale: 0.9, disabled: !!disabled });\n\n    const dim = size === \"sm\" ? 16 : size === \"lg\" ? 22 : 18;\n\n    return (\n      <Animated.View style={press.style}>\n        <Pressable\n          ref={ref}\n          accessibilityRole=\"checkbox\"\n          accessibilityState={{\n            checked: checked === \"indeterminate\" ? \"mixed\" : !!checked,\n            disabled: !!disabled,\n          }}\n          disabled={disabled}\n          onPressIn={(e) => {\n            press.onPressIn();\n            onPressIn?.(e);\n          }}\n          onPressOut={(e) => {\n            press.onPressOut();\n            onPressOut?.(e);\n          }}\n          onPress={() => {\n            const next = checked !== true;\n            if (!isControlled) setInternal(next);\n            onCheckedChange?.(next);\n          }}\n          style={cn(\n            {\n              width: dim,\n              height: dim,\n              borderRadius: theme.radii.md,\n              borderWidth: 1,\n              borderColor: isOn\n                ? \"rgba(26,26,26,0.35)\"\n                : colors.glassChromeBorder,\n              backgroundColor: isOn\n                ? colors.primary\n                : variant === \"outline\"\n                  ? colors.glassSurfaceFill\n                  : colors.glassChromeBgEnv,\n              alignItems: \"center\",\n              justifyContent: \"center\",\n              opacity: disabled ? 0.5 : 1,\n            },\n            style,\n          )}\n          {...props}\n        >\n          {isOn ? (\n            <Animated.View\n              style={{\n                opacity: checkAnim,\n                transform: [\n                  {\n                    scale: checkAnim.interpolate({\n                      inputRange: [0, 1],\n                      outputRange: [0.5, 1],\n                    }),\n                  },\n                ],\n              }}\n            >\n              <Text\n                style={{\n                  color: colors.primaryForeground,\n                  fontSize: dim * 0.65,\n                  fontWeight: \"700\",\n                  lineHeight: dim,\n                }}\n              >\n                {checked === \"indeterminate\" ? \"−\" : \"✓\"}\n              </Text>\n            </Animated.View>\n          ) : null}\n        </Pressable>\n      </Animated.View>\n    );\n  },\n);\nCheckbox.displayName = \"Checkbox\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "collapsible",
      "type": "registry:ui",
      "title": "Collapsible",
      "description": "React Native Collapsible for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/collapsible.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/collapsible.tsx",
          "content": "import {\n  createContext,\n  useContext,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  LayoutAnimation,\n  Platform,\n  Pressable,\n  UIManager,\n  View,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { cn } from \"../utils/cn\";\n\nif (\n  Platform.OS === \"android\" &&\n  UIManager.setLayoutAnimationEnabledExperimental\n) {\n  UIManager.setLayoutAnimationEnabledExperimental(true);\n}\n\ninterface CollapsibleContextValue {\n  open: boolean;\n  setOpen: (open: boolean) => void;\n}\n\nconst CollapsibleContext = createContext<CollapsibleContextValue | null>(null);\n\nexport interface CollapsibleProps extends ViewProps {\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport function Collapsible({\n  open: openProp,\n  defaultOpen = false,\n  onOpenChange,\n  children,\n  style,\n  ...props\n}: CollapsibleProps) {\n  const isControlled = openProp !== undefined;\n  const [internal, setInternal] = useState(defaultOpen);\n  const open = isControlled ? !!openProp : internal;\n  const setOpen = (next: boolean) => {\n    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);\n    if (!isControlled) setInternal(next);\n    onOpenChange?.(next);\n  };\n\n  return (\n    <CollapsibleContext.Provider value={{ open, setOpen }}>\n      <View style={style} {...props}>\n        {children}\n      </View>\n    </CollapsibleContext.Provider>\n  );\n}\n\nexport function CollapsibleTrigger({\n  children,\n  style,\n}: {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}) {\n  const ctx = useContext(CollapsibleContext);\n  if (!ctx) throw new Error(\"CollapsibleTrigger must be within Collapsible\");\n  return (\n    <Pressable\n      accessibilityRole=\"button\"\n      accessibilityState={{ expanded: ctx.open }}\n      onPress={() => ctx.setOpen(!ctx.open)}\n      style={style}\n    >\n      {children}\n    </Pressable>\n  );\n}\n\nexport function CollapsibleContent({\n  children,\n  style,\n  ...props\n}: ViewProps & { style?: StyleProp<ViewStyle> }) {\n  const ctx = useContext(CollapsibleContext);\n  if (!ctx || !ctx.open) return null;\n  return (\n    <View style={cn(style)} {...props}>\n      {children}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "color-picker",
      "type": "registry:ui",
      "title": "Color Picker",
      "description": "React Native Color Picker for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/color-picker.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/color-picker.tsx",
          "content": "import { Pressable, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nconst SWATCHES = [\"#111111\", \"#6366f1\", \"#0ea5e9\", \"#22c55e\", \"#f59e0b\", \"#ef4444\", \"#f8fafc\"];\n\nexport function ColorPicker({\n  value,\n  onChange,\n  swatches = SWATCHES,\n}: {\n  value?: string;\n  onChange?: (value: string) => void;\n  swatches?: string[];\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", flexWrap: \"wrap\", gap: theme.spacing[2] }}>\n      {swatches.map((hex) => (\n        <Pressable\n          key={hex}\n          onPress={() => onChange?.(hex)}\n          style={{\n            width: 28,\n            height: 28,\n            borderRadius: 14,\n            backgroundColor: hex,\n            borderWidth: value === hex ? 2 : 1,\n            borderColor: value === hex ? colors.primary : colors.glassChromeBorder,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "combobox",
      "type": "registry:ui",
      "title": "Combobox",
      "description": "React Native Combobox for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/combobox.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/combobox.tsx",
          "content": "import { useMemo, useState } from \"react\";\nimport { Pressable, Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Input } from \"./input\";\n\nexport type ComboboxOption = { value: string; label: string };\n\nexport function Combobox({\n  options,\n  value,\n  onValueChange,\n  placeholder = \"Search…\",\n}: {\n  options: ComboboxOption[];\n  value?: string;\n  onValueChange?: (value: string) => void;\n  placeholder?: string;\n}) {\n  const { theme, colors } = useTheme();\n  const [query, setQuery] = useState(\"\");\n  const filtered = useMemo(() => {\n    const q = query.trim().toLowerCase();\n    return options.filter(\n      (o) =>\n        !q ||\n        o.label.toLowerCase().includes(q) ||\n        o.value.toLowerCase().includes(q),\n    );\n  }, [options, query]);\n\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      <Input value={query} onChangeText={setQuery} placeholder={placeholder} />\n      {filtered.slice(0, 6).map((o) => {\n        const active = o.value === value;\n        return (\n          <Pressable\n            key={o.value}\n            onPress={() => onValueChange?.(o.value)}\n            style={{\n              padding: theme.spacing[2],\n              borderRadius: theme.radii.md,\n              backgroundColor: active ? colors.glassSurfaceFill : \"transparent\",\n            }}\n          >\n            <Text style={{ color: colors.foreground }}>{o.label}</Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function MultiSelect({\n  options,\n  value,\n  onValueChange,\n}: {\n  options: ComboboxOption[];\n  value: string[];\n  onValueChange: (value: string[]) => void;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => {\n        const on = value.includes(o.value);\n        return (\n          <Pressable\n            key={o.value}\n            onPress={() =>\n              onValueChange(on ? value.filter((v) => v !== o.value) : [...value, o.value])\n            }\n            style={{\n              padding: theme.spacing[2],\n              borderRadius: theme.radii.md,\n              borderWidth: 1,\n              borderColor: on ? colors.primary : colors.glassChromeBorder,\n            }}\n          >\n            <Text style={{ color: colors.foreground }}>\n              {on ? \"✓ \" : \"\"}\n              {o.label}\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function Command({\n  options,\n  onSelect,\n}: {\n  options: ComboboxOption[];\n  onSelect?: (value: string) => void;\n}) {\n  return <Combobox options={options} onValueChange={onSelect} placeholder=\"Type a command\" />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "multi-select",
      "type": "registry:ui",
      "title": "Multi Select",
      "description": "React Native Multi Select for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/combobox.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/combobox.tsx",
          "content": "import { useMemo, useState } from \"react\";\nimport { Pressable, Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Input } from \"./input\";\n\nexport type ComboboxOption = { value: string; label: string };\n\nexport function Combobox({\n  options,\n  value,\n  onValueChange,\n  placeholder = \"Search…\",\n}: {\n  options: ComboboxOption[];\n  value?: string;\n  onValueChange?: (value: string) => void;\n  placeholder?: string;\n}) {\n  const { theme, colors } = useTheme();\n  const [query, setQuery] = useState(\"\");\n  const filtered = useMemo(() => {\n    const q = query.trim().toLowerCase();\n    return options.filter(\n      (o) =>\n        !q ||\n        o.label.toLowerCase().includes(q) ||\n        o.value.toLowerCase().includes(q),\n    );\n  }, [options, query]);\n\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      <Input value={query} onChangeText={setQuery} placeholder={placeholder} />\n      {filtered.slice(0, 6).map((o) => {\n        const active = o.value === value;\n        return (\n          <Pressable\n            key={o.value}\n            onPress={() => onValueChange?.(o.value)}\n            style={{\n              padding: theme.spacing[2],\n              borderRadius: theme.radii.md,\n              backgroundColor: active ? colors.glassSurfaceFill : \"transparent\",\n            }}\n          >\n            <Text style={{ color: colors.foreground }}>{o.label}</Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function MultiSelect({\n  options,\n  value,\n  onValueChange,\n}: {\n  options: ComboboxOption[];\n  value: string[];\n  onValueChange: (value: string[]) => void;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => {\n        const on = value.includes(o.value);\n        return (\n          <Pressable\n            key={o.value}\n            onPress={() =>\n              onValueChange(on ? value.filter((v) => v !== o.value) : [...value, o.value])\n            }\n            style={{\n              padding: theme.spacing[2],\n              borderRadius: theme.radii.md,\n              borderWidth: 1,\n              borderColor: on ? colors.primary : colors.glassChromeBorder,\n            }}\n          >\n            <Text style={{ color: colors.foreground }}>\n              {on ? \"✓ \" : \"\"}\n              {o.label}\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function Command({\n  options,\n  onSelect,\n}: {\n  options: ComboboxOption[];\n  onSelect?: (value: string) => void;\n}) {\n  return <Combobox options={options} onValueChange={onSelect} placeholder=\"Type a command\" />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "command",
      "type": "registry:ui",
      "title": "Command",
      "description": "React Native Command for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/combobox.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/combobox.tsx",
          "content": "import { useMemo, useState } from \"react\";\nimport { Pressable, Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Input } from \"./input\";\n\nexport type ComboboxOption = { value: string; label: string };\n\nexport function Combobox({\n  options,\n  value,\n  onValueChange,\n  placeholder = \"Search…\",\n}: {\n  options: ComboboxOption[];\n  value?: string;\n  onValueChange?: (value: string) => void;\n  placeholder?: string;\n}) {\n  const { theme, colors } = useTheme();\n  const [query, setQuery] = useState(\"\");\n  const filtered = useMemo(() => {\n    const q = query.trim().toLowerCase();\n    return options.filter(\n      (o) =>\n        !q ||\n        o.label.toLowerCase().includes(q) ||\n        o.value.toLowerCase().includes(q),\n    );\n  }, [options, query]);\n\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      <Input value={query} onChangeText={setQuery} placeholder={placeholder} />\n      {filtered.slice(0, 6).map((o) => {\n        const active = o.value === value;\n        return (\n          <Pressable\n            key={o.value}\n            onPress={() => onValueChange?.(o.value)}\n            style={{\n              padding: theme.spacing[2],\n              borderRadius: theme.radii.md,\n              backgroundColor: active ? colors.glassSurfaceFill : \"transparent\",\n            }}\n          >\n            <Text style={{ color: colors.foreground }}>{o.label}</Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function MultiSelect({\n  options,\n  value,\n  onValueChange,\n}: {\n  options: ComboboxOption[];\n  value: string[];\n  onValueChange: (value: string[]) => void;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => {\n        const on = value.includes(o.value);\n        return (\n          <Pressable\n            key={o.value}\n            onPress={() =>\n              onValueChange(on ? value.filter((v) => v !== o.value) : [...value, o.value])\n            }\n            style={{\n              padding: theme.spacing[2],\n              borderRadius: theme.radii.md,\n              borderWidth: 1,\n              borderColor: on ? colors.primary : colors.glassChromeBorder,\n            }}\n          >\n            <Text style={{ color: colors.foreground }}>\n              {on ? \"✓ \" : \"\"}\n              {o.label}\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n\nexport function Command({\n  options,\n  onSelect,\n}: {\n  options: ComboboxOption[];\n  onSelect?: (value: string) => void;\n}) {\n  return <Combobox options={options} onValueChange={onSelect} placeholder=\"Type a command\" />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "context-menu",
      "type": "registry:ui",
      "title": "Context Menu",
      "description": "React Native Context Menu for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "dropdown-menu"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/context-menu.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/context-menu.tsx",
          "content": "export {\n  ContextMenu,\n  ContextMenuTrigger,\n  ContextMenuContent,\n  ContextMenuItem,\n} from \"./dropdown-menu\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "copy-button",
      "type": "registry:ui",
      "title": "Copy Button",
      "description": "React Native Copy Button for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "button"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/copy-button.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/copy-button.tsx",
          "content": "import { useState } from \"react\";\nimport { Button, type ButtonProps } from \"./button\";\n\nexport interface CopyButtonProps extends Omit<ButtonProps, \"onPress\"> {\n  value: string;\n  copiedLabel?: string;\n}\n\nexport function CopyButton({\n  value,\n  copiedLabel = \"Copied\",\n  children = \"Copy\",\n  ...props\n}: CopyButtonProps) {\n  const [copied, setCopied] = useState(false);\n\n  return (\n    <Button\n      {...props}\n      onPress={() => {\n        try {\n          // Optional Expo clipboard; no-op if the peer is missing.\n          // eslint-disable-next-line @typescript-eslint/no-require-imports\n          const clip = require(\"expo-clipboard\") as {\n            setStringAsync?: (v: string) => Promise<void>;\n          };\n          void clip.setStringAsync?.(value);\n        } catch {\n          /* clipboard optional */\n        }\n        setCopied(true);\n        setTimeout(() => setCopied(false), 1500);\n      }}\n    >\n      {copied ? copiedLabel : children}\n    </Button>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "kanban",
      "type": "registry:ui",
      "title": "Kanban",
      "description": "React Native Kanban for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "table"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/data-views.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/data-views.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport function Kanban({\n  columns,\n}: {\n  columns: Array<{ title: string; cards: string[] }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n      {columns.map((col) => (\n        <View\n          key={col.title}\n          style={{\n            flex: 1,\n            gap: theme.spacing[2],\n            padding: theme.spacing[2],\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n          }}\n        >\n          <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n            {col.title}\n          </Text>\n          {col.cards.map((c) => (\n            <Card key={c} variant=\"chrome\">\n              <CardContent>\n                <Text style={{ color: colors.foreground }}>{c}</Text>\n              </CardContent>\n            </Card>\n          ))}\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function DataGrid({\n  columns,\n  rows,\n}: {\n  columns: string[];\n  rows: string[][];\n}) {\n  return (\n    <Table>\n      <TableHeader>\n        <TableRow>\n          {columns.map((c) => (\n            <TableHead key={c}>{c}</TableHead>\n          ))}\n        </TableRow>\n      </TableHeader>\n      <TableBody>\n        {rows.map((row, i) => (\n          <TableRow key={i}>\n            {row.map((cell, j) => (\n              <TableCell key={j}>{cell}</TableCell>\n            ))}\n          </TableRow>\n        ))}\n      </TableBody>\n    </Table>\n  );\n}\n\nexport function VirtualTable(props: { columns: string[]; rows: string[][] }) {\n  return <DataGrid {...props} />;\n}\n\nexport function AddressFields({\n  values,\n}: {\n  values?: { line1?: string; city?: string; country?: string };\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Address</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Text style={{ color: colors.foreground }}>{values?.line1 ?? \"Street\"}</Text>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {[values?.city, values?.country].filter(Boolean).join(\", \") || \"City, Country\"}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AddressCountrySelect() {\n  return <AddressFields values={{ country: \"United States\" }} />;\n}\n\nexport function AddressRegionSelect() {\n  return <AddressFields values={{ city: \"California\" }} />;\n}\n\nexport function AddressCitySelect() {\n  return <AddressFields values={{ city: \"San Francisco\" }} />;\n}\n\nexport function EventCalendar() {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Events</CardTitle>\n      </CardHeader>\n    </Card>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "data-grid",
      "type": "registry:ui",
      "title": "Data Grid",
      "description": "React Native Data Grid for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "table"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/data-views.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/data-views.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport function Kanban({\n  columns,\n}: {\n  columns: Array<{ title: string; cards: string[] }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n      {columns.map((col) => (\n        <View\n          key={col.title}\n          style={{\n            flex: 1,\n            gap: theme.spacing[2],\n            padding: theme.spacing[2],\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n          }}\n        >\n          <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n            {col.title}\n          </Text>\n          {col.cards.map((c) => (\n            <Card key={c} variant=\"chrome\">\n              <CardContent>\n                <Text style={{ color: colors.foreground }}>{c}</Text>\n              </CardContent>\n            </Card>\n          ))}\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function DataGrid({\n  columns,\n  rows,\n}: {\n  columns: string[];\n  rows: string[][];\n}) {\n  return (\n    <Table>\n      <TableHeader>\n        <TableRow>\n          {columns.map((c) => (\n            <TableHead key={c}>{c}</TableHead>\n          ))}\n        </TableRow>\n      </TableHeader>\n      <TableBody>\n        {rows.map((row, i) => (\n          <TableRow key={i}>\n            {row.map((cell, j) => (\n              <TableCell key={j}>{cell}</TableCell>\n            ))}\n          </TableRow>\n        ))}\n      </TableBody>\n    </Table>\n  );\n}\n\nexport function VirtualTable(props: { columns: string[]; rows: string[][] }) {\n  return <DataGrid {...props} />;\n}\n\nexport function AddressFields({\n  values,\n}: {\n  values?: { line1?: string; city?: string; country?: string };\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Address</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Text style={{ color: colors.foreground }}>{values?.line1 ?? \"Street\"}</Text>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {[values?.city, values?.country].filter(Boolean).join(\", \") || \"City, Country\"}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AddressCountrySelect() {\n  return <AddressFields values={{ country: \"United States\" }} />;\n}\n\nexport function AddressRegionSelect() {\n  return <AddressFields values={{ city: \"California\" }} />;\n}\n\nexport function AddressCitySelect() {\n  return <AddressFields values={{ city: \"San Francisco\" }} />;\n}\n\nexport function EventCalendar() {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Events</CardTitle>\n      </CardHeader>\n    </Card>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "virtual-table",
      "type": "registry:ui",
      "title": "Virtual Table",
      "description": "React Native Virtual Table for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "table"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/data-views.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/data-views.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport function Kanban({\n  columns,\n}: {\n  columns: Array<{ title: string; cards: string[] }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n      {columns.map((col) => (\n        <View\n          key={col.title}\n          style={{\n            flex: 1,\n            gap: theme.spacing[2],\n            padding: theme.spacing[2],\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n          }}\n        >\n          <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n            {col.title}\n          </Text>\n          {col.cards.map((c) => (\n            <Card key={c} variant=\"chrome\">\n              <CardContent>\n                <Text style={{ color: colors.foreground }}>{c}</Text>\n              </CardContent>\n            </Card>\n          ))}\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function DataGrid({\n  columns,\n  rows,\n}: {\n  columns: string[];\n  rows: string[][];\n}) {\n  return (\n    <Table>\n      <TableHeader>\n        <TableRow>\n          {columns.map((c) => (\n            <TableHead key={c}>{c}</TableHead>\n          ))}\n        </TableRow>\n      </TableHeader>\n      <TableBody>\n        {rows.map((row, i) => (\n          <TableRow key={i}>\n            {row.map((cell, j) => (\n              <TableCell key={j}>{cell}</TableCell>\n            ))}\n          </TableRow>\n        ))}\n      </TableBody>\n    </Table>\n  );\n}\n\nexport function VirtualTable(props: { columns: string[]; rows: string[][] }) {\n  return <DataGrid {...props} />;\n}\n\nexport function AddressFields({\n  values,\n}: {\n  values?: { line1?: string; city?: string; country?: string };\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Address</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Text style={{ color: colors.foreground }}>{values?.line1 ?? \"Street\"}</Text>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {[values?.city, values?.country].filter(Boolean).join(\", \") || \"City, Country\"}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AddressCountrySelect() {\n  return <AddressFields values={{ country: \"United States\" }} />;\n}\n\nexport function AddressRegionSelect() {\n  return <AddressFields values={{ city: \"California\" }} />;\n}\n\nexport function AddressCitySelect() {\n  return <AddressFields values={{ city: \"San Francisco\" }} />;\n}\n\nexport function EventCalendar() {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Events</CardTitle>\n      </CardHeader>\n    </Card>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "address-fields",
      "type": "registry:ui",
      "title": "Address Fields",
      "description": "React Native Address Fields for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "table"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/data-views.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/data-views.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport function Kanban({\n  columns,\n}: {\n  columns: Array<{ title: string; cards: string[] }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n      {columns.map((col) => (\n        <View\n          key={col.title}\n          style={{\n            flex: 1,\n            gap: theme.spacing[2],\n            padding: theme.spacing[2],\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n          }}\n        >\n          <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n            {col.title}\n          </Text>\n          {col.cards.map((c) => (\n            <Card key={c} variant=\"chrome\">\n              <CardContent>\n                <Text style={{ color: colors.foreground }}>{c}</Text>\n              </CardContent>\n            </Card>\n          ))}\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function DataGrid({\n  columns,\n  rows,\n}: {\n  columns: string[];\n  rows: string[][];\n}) {\n  return (\n    <Table>\n      <TableHeader>\n        <TableRow>\n          {columns.map((c) => (\n            <TableHead key={c}>{c}</TableHead>\n          ))}\n        </TableRow>\n      </TableHeader>\n      <TableBody>\n        {rows.map((row, i) => (\n          <TableRow key={i}>\n            {row.map((cell, j) => (\n              <TableCell key={j}>{cell}</TableCell>\n            ))}\n          </TableRow>\n        ))}\n      </TableBody>\n    </Table>\n  );\n}\n\nexport function VirtualTable(props: { columns: string[]; rows: string[][] }) {\n  return <DataGrid {...props} />;\n}\n\nexport function AddressFields({\n  values,\n}: {\n  values?: { line1?: string; city?: string; country?: string };\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Address</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Text style={{ color: colors.foreground }}>{values?.line1 ?? \"Street\"}</Text>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {[values?.city, values?.country].filter(Boolean).join(\", \") || \"City, Country\"}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AddressCountrySelect() {\n  return <AddressFields values={{ country: \"United States\" }} />;\n}\n\nexport function AddressRegionSelect() {\n  return <AddressFields values={{ city: \"California\" }} />;\n}\n\nexport function AddressCitySelect() {\n  return <AddressFields values={{ city: \"San Francisco\" }} />;\n}\n\nexport function EventCalendar() {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Events</CardTitle>\n      </CardHeader>\n    </Card>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "address-country-select",
      "type": "registry:ui",
      "title": "Address Country Select",
      "description": "React Native Address Country Select for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "table"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/data-views.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/data-views.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport function Kanban({\n  columns,\n}: {\n  columns: Array<{ title: string; cards: string[] }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n      {columns.map((col) => (\n        <View\n          key={col.title}\n          style={{\n            flex: 1,\n            gap: theme.spacing[2],\n            padding: theme.spacing[2],\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n          }}\n        >\n          <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n            {col.title}\n          </Text>\n          {col.cards.map((c) => (\n            <Card key={c} variant=\"chrome\">\n              <CardContent>\n                <Text style={{ color: colors.foreground }}>{c}</Text>\n              </CardContent>\n            </Card>\n          ))}\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function DataGrid({\n  columns,\n  rows,\n}: {\n  columns: string[];\n  rows: string[][];\n}) {\n  return (\n    <Table>\n      <TableHeader>\n        <TableRow>\n          {columns.map((c) => (\n            <TableHead key={c}>{c}</TableHead>\n          ))}\n        </TableRow>\n      </TableHeader>\n      <TableBody>\n        {rows.map((row, i) => (\n          <TableRow key={i}>\n            {row.map((cell, j) => (\n              <TableCell key={j}>{cell}</TableCell>\n            ))}\n          </TableRow>\n        ))}\n      </TableBody>\n    </Table>\n  );\n}\n\nexport function VirtualTable(props: { columns: string[]; rows: string[][] }) {\n  return <DataGrid {...props} />;\n}\n\nexport function AddressFields({\n  values,\n}: {\n  values?: { line1?: string; city?: string; country?: string };\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Address</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Text style={{ color: colors.foreground }}>{values?.line1 ?? \"Street\"}</Text>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {[values?.city, values?.country].filter(Boolean).join(\", \") || \"City, Country\"}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AddressCountrySelect() {\n  return <AddressFields values={{ country: \"United States\" }} />;\n}\n\nexport function AddressRegionSelect() {\n  return <AddressFields values={{ city: \"California\" }} />;\n}\n\nexport function AddressCitySelect() {\n  return <AddressFields values={{ city: \"San Francisco\" }} />;\n}\n\nexport function EventCalendar() {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Events</CardTitle>\n      </CardHeader>\n    </Card>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "address-region-select",
      "type": "registry:ui",
      "title": "Address Region Select",
      "description": "React Native Address Region Select for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "table"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/data-views.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/data-views.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport function Kanban({\n  columns,\n}: {\n  columns: Array<{ title: string; cards: string[] }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n      {columns.map((col) => (\n        <View\n          key={col.title}\n          style={{\n            flex: 1,\n            gap: theme.spacing[2],\n            padding: theme.spacing[2],\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n          }}\n        >\n          <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n            {col.title}\n          </Text>\n          {col.cards.map((c) => (\n            <Card key={c} variant=\"chrome\">\n              <CardContent>\n                <Text style={{ color: colors.foreground }}>{c}</Text>\n              </CardContent>\n            </Card>\n          ))}\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function DataGrid({\n  columns,\n  rows,\n}: {\n  columns: string[];\n  rows: string[][];\n}) {\n  return (\n    <Table>\n      <TableHeader>\n        <TableRow>\n          {columns.map((c) => (\n            <TableHead key={c}>{c}</TableHead>\n          ))}\n        </TableRow>\n      </TableHeader>\n      <TableBody>\n        {rows.map((row, i) => (\n          <TableRow key={i}>\n            {row.map((cell, j) => (\n              <TableCell key={j}>{cell}</TableCell>\n            ))}\n          </TableRow>\n        ))}\n      </TableBody>\n    </Table>\n  );\n}\n\nexport function VirtualTable(props: { columns: string[]; rows: string[][] }) {\n  return <DataGrid {...props} />;\n}\n\nexport function AddressFields({\n  values,\n}: {\n  values?: { line1?: string; city?: string; country?: string };\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Address</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Text style={{ color: colors.foreground }}>{values?.line1 ?? \"Street\"}</Text>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {[values?.city, values?.country].filter(Boolean).join(\", \") || \"City, Country\"}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AddressCountrySelect() {\n  return <AddressFields values={{ country: \"United States\" }} />;\n}\n\nexport function AddressRegionSelect() {\n  return <AddressFields values={{ city: \"California\" }} />;\n}\n\nexport function AddressCitySelect() {\n  return <AddressFields values={{ city: \"San Francisco\" }} />;\n}\n\nexport function EventCalendar() {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Events</CardTitle>\n      </CardHeader>\n    </Card>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "address-city-select",
      "type": "registry:ui",
      "title": "Address City Select",
      "description": "React Native Address City Select for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "table"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/data-views.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/data-views.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport function Kanban({\n  columns,\n}: {\n  columns: Array<{ title: string; cards: string[] }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n      {columns.map((col) => (\n        <View\n          key={col.title}\n          style={{\n            flex: 1,\n            gap: theme.spacing[2],\n            padding: theme.spacing[2],\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n          }}\n        >\n          <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n            {col.title}\n          </Text>\n          {col.cards.map((c) => (\n            <Card key={c} variant=\"chrome\">\n              <CardContent>\n                <Text style={{ color: colors.foreground }}>{c}</Text>\n              </CardContent>\n            </Card>\n          ))}\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function DataGrid({\n  columns,\n  rows,\n}: {\n  columns: string[];\n  rows: string[][];\n}) {\n  return (\n    <Table>\n      <TableHeader>\n        <TableRow>\n          {columns.map((c) => (\n            <TableHead key={c}>{c}</TableHead>\n          ))}\n        </TableRow>\n      </TableHeader>\n      <TableBody>\n        {rows.map((row, i) => (\n          <TableRow key={i}>\n            {row.map((cell, j) => (\n              <TableCell key={j}>{cell}</TableCell>\n            ))}\n          </TableRow>\n        ))}\n      </TableBody>\n    </Table>\n  );\n}\n\nexport function VirtualTable(props: { columns: string[]; rows: string[][] }) {\n  return <DataGrid {...props} />;\n}\n\nexport function AddressFields({\n  values,\n}: {\n  values?: { line1?: string; city?: string; country?: string };\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Address</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Text style={{ color: colors.foreground }}>{values?.line1 ?? \"Street\"}</Text>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {[values?.city, values?.country].filter(Boolean).join(\", \") || \"City, Country\"}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AddressCountrySelect() {\n  return <AddressFields values={{ country: \"United States\" }} />;\n}\n\nexport function AddressRegionSelect() {\n  return <AddressFields values={{ city: \"California\" }} />;\n}\n\nexport function AddressCitySelect() {\n  return <AddressFields values={{ city: \"San Francisco\" }} />;\n}\n\nexport function EventCalendar() {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Events</CardTitle>\n      </CardHeader>\n    </Card>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "event-calendar",
      "type": "registry:ui",
      "title": "Event Calendar",
      "description": "React Native Event Calendar for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "card",
        "table"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/data-views.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/data-views.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"./card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport function Kanban({\n  columns,\n}: {\n  columns: Array<{ title: string; cards: string[] }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n      {columns.map((col) => (\n        <View\n          key={col.title}\n          style={{\n            flex: 1,\n            gap: theme.spacing[2],\n            padding: theme.spacing[2],\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n          }}\n        >\n          <Text style={{ fontWeight: theme.fontWeights.semibold, color: colors.foreground }}>\n            {col.title}\n          </Text>\n          {col.cards.map((c) => (\n            <Card key={c} variant=\"chrome\">\n              <CardContent>\n                <Text style={{ color: colors.foreground }}>{c}</Text>\n              </CardContent>\n            </Card>\n          ))}\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function DataGrid({\n  columns,\n  rows,\n}: {\n  columns: string[];\n  rows: string[][];\n}) {\n  return (\n    <Table>\n      <TableHeader>\n        <TableRow>\n          {columns.map((c) => (\n            <TableHead key={c}>{c}</TableHead>\n          ))}\n        </TableRow>\n      </TableHeader>\n      <TableBody>\n        {rows.map((row, i) => (\n          <TableRow key={i}>\n            {row.map((cell, j) => (\n              <TableCell key={j}>{cell}</TableCell>\n            ))}\n          </TableRow>\n        ))}\n      </TableBody>\n    </Table>\n  );\n}\n\nexport function VirtualTable(props: { columns: string[]; rows: string[][] }) {\n  return <DataGrid {...props} />;\n}\n\nexport function AddressFields({\n  values,\n}: {\n  values?: { line1?: string; city?: string; country?: string };\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Address</CardTitle>\n      </CardHeader>\n      <CardContent>\n        <Text style={{ color: colors.foreground }}>{values?.line1 ?? \"Street\"}</Text>\n        <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n          {[values?.city, values?.country].filter(Boolean).join(\", \") || \"City, Country\"}\n        </Text>\n      </CardContent>\n    </Card>\n  );\n}\n\nexport function AddressCountrySelect() {\n  return <AddressFields values={{ country: \"United States\" }} />;\n}\n\nexport function AddressRegionSelect() {\n  return <AddressFields values={{ city: \"California\" }} />;\n}\n\nexport function AddressCitySelect() {\n  return <AddressFields values={{ city: \"San Francisco\" }} />;\n}\n\nexport function EventCalendar() {\n  return (\n    <Card variant=\"chrome\">\n      <CardHeader>\n        <CardTitle>Events</CardTitle>\n      </CardHeader>\n    </Card>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "dialog",
      "type": "registry:ui",
      "title": "Dialog",
      "description": "React Native Dialog for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/dialog.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/dialog.tsx",
          "content": "import {\n  createContext,\n  forwardRef,\n  useContext,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  Animated,\n  Modal,\n  Pressable,\n  Text,\n  View,\n  type StyleProp,\n  type TextProps,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport {\n  dialogContentStyle,\n  overlayStyle,\n  timings,\n  usePresence,\n} from \"../utils/animation\";\nimport { cn } from \"../utils/cn\";\n\ninterface DialogContextValue {\n  open: boolean;\n  setOpen: (open: boolean) => void;\n}\n\nconst DialogContext = createContext<DialogContextValue | null>(null);\n\nfunction useDialog() {\n  const ctx = useContext(DialogContext);\n  if (!ctx) throw new Error(\"Dialog components must be used within Dialog\");\n  return ctx;\n}\n\nexport interface DialogProps {\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  children?: ReactNode;\n}\n\nexport function Dialog({\n  open: openProp,\n  defaultOpen = false,\n  onOpenChange,\n  children,\n}: DialogProps) {\n  const isControlled = openProp !== undefined;\n  const [internal, setInternal] = useState(defaultOpen);\n  const open = isControlled ? !!openProp : internal;\n  const setOpen = (next: boolean) => {\n    if (!isControlled) setInternal(next);\n    onOpenChange?.(next);\n  };\n  return (\n    <DialogContext.Provider value={{ open, setOpen }}>\n      {children}\n    </DialogContext.Provider>\n  );\n}\n\nexport function DialogTrigger({\n  children,\n  asChild,\n}: {\n  children: ReactNode;\n  asChild?: boolean;\n}) {\n  const { setOpen } = useDialog();\n  if (asChild && typeof children === \"object\" && children !== null && \"props\" in (children as object)) {\n    // consumers should wrap Pressable themselves\n  }\n  return (\n    <Pressable onPress={() => setOpen(true)} accessibilityRole=\"button\">\n      {children}\n    </Pressable>\n  );\n}\n\nexport function DialogClose({ children }: { children?: ReactNode }) {\n  const { setOpen } = useDialog();\n  return (\n    <Pressable onPress={() => setOpen(false)} accessibilityRole=\"button\">\n      {children}\n    </Pressable>\n  );\n}\n\nexport type DialogOverlayBlur = \"none\" | \"sm\" | \"default\" | \"lg\" | \"xl\" | \"heavy\";\nexport type DialogOverlayDim = \"none\" | \"light\" | \"default\" | \"heavy\";\n\nexport interface DialogContentProps extends ViewProps {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n  dim?: DialogOverlayDim;\n  showClose?: boolean;\n}\n\nexport function DialogContent({\n  children,\n  style,\n  dim = \"default\",\n  showClose = true,\n  ...props\n}: DialogContentProps) {\n  const { theme, colors } = useTheme();\n  const { open, setOpen } = useDialog();\n  const { mounted, progress } = usePresence(open, timings.normal);\n\n  const overlayBg =\n    dim === \"none\"\n      ? \"transparent\"\n      : dim === \"light\"\n        ? \"rgba(0,0,0,0.12)\"\n        : dim === \"heavy\"\n          ? colors.overlayHeavy\n          : colors.overlay;\n\n  if (!mounted) return null;\n\n  return (\n    <Modal\n      visible={mounted}\n      transparent\n      animationType=\"none\"\n      onRequestClose={() => setOpen(false)}\n    >\n      <View style={{ flex: 1 }}>\n        <Animated.View\n          pointerEvents=\"none\"\n          style={[\n            {\n              ...StyleSheetAbsoluteFill,\n              backgroundColor: overlayBg,\n            },\n            overlayStyle(progress),\n          ]}\n        />\n        <Pressable\n          style={{\n            flex: 1,\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            padding: theme.spacing[6],\n          }}\n          onPress={() => setOpen(false)}\n        >\n          <Animated.View style={dialogContentStyle(progress)}>\n            <Pressable\n              onPress={(e) => e.stopPropagation?.()}\n              style={cn(\n                {\n                  width: \"100%\",\n                  maxWidth: 420,\n                  borderRadius: theme.radii[\"2xl\"],\n                  backgroundColor: colors.popover,\n                  borderWidth: 1,\n                  borderColor: colors.glassChromeBorder,\n                  padding: theme.spacing[6],\n                },\n                style,\n              )}\n              {...props}\n            >\n              {showClose ? (\n                <Pressable\n                  onPress={() => setOpen(false)}\n                  accessibilityLabel=\"Close\"\n                  style={{\n                    position: \"absolute\",\n                    top: theme.spacing[3],\n                    right: theme.spacing[3],\n                    zIndex: 1,\n                    padding: theme.spacing[2],\n                  }}\n                >\n                  <Text style={{ color: colors.mutedForeground, fontSize: 18 }}>✕</Text>\n                </Pressable>\n              ) : null}\n              {children}\n            </Pressable>\n          </Animated.View>\n        </Pressable>\n      </View>\n    </Modal>\n  );\n}\n\nconst StyleSheetAbsoluteFill = {\n  position: \"absolute\" as const,\n  left: 0,\n  right: 0,\n  top: 0,\n  bottom: 0,\n};\n\nexport const DialogHeader = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flexDirection: \"column\",\n            gap: theme.spacing[1.5],\n            marginBottom: theme.spacing[4],\n            paddingRight: theme.spacing[6],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nexport const DialogFooter = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flexDirection: \"row\",\n            justifyContent: \"flex-end\",\n            gap: theme.spacing[2],\n            marginTop: theme.spacing[4],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nDialogFooter.displayName = \"DialogFooter\";\n\nexport const DialogTitle = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        accessibilityRole=\"header\"\n        style={cn(\n          {\n            color: colors.foreground,\n            fontSize: theme.fontSizes.lg,\n            fontWeight: theme.fontWeights.semibold,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nDialogTitle.displayName = \"DialogTitle\";\n\nexport const DialogDescription = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color: colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n            lineHeight: theme.fontSizes.sm * theme.lineHeights.relaxed,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nDialogDescription.displayName = \"DialogDescription\";\n\nexport const DialogPortal = ({ children }: { children?: ReactNode }) => (\n  <>{children}</>\n);\nexport const DialogOverlay = ({ children }: { children?: ReactNode }) => (\n  <>{children}</>\n);\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "drawer",
      "type": "registry:ui",
      "title": "Drawer",
      "description": "React Native Drawer for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "sheet"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/drawer.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/drawer.tsx",
          "content": "export {\n  Sheet as Drawer,\n  SheetTrigger as DrawerTrigger,\n  SheetContent as DrawerContent,\n  SheetHeader as DrawerHeader,\n  SheetFooter as DrawerFooter,\n  SheetTitle as DrawerTitle,\n  SheetDescription as DrawerDescription,\n  SheetClose as DrawerClose,\n} from \"./sheet\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "dropdown-menu",
      "type": "registry:ui",
      "title": "Dropdown Menu",
      "description": "React Native Dropdown Menu for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "popover"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/dropdown-menu.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/dropdown-menu.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Pressable, Text } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from \"./popover\";\n\nexport const DropdownMenu = Popover;\nexport const DropdownMenuTrigger = PopoverTrigger;\nexport const DropdownMenuContent = PopoverContent;\n\nexport function DropdownMenuItem({\n  children,\n  onSelect,\n}: {\n  children?: ReactNode;\n  onSelect?: () => void;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <Pressable\n      onPress={onSelect}\n      style={{\n        paddingVertical: theme.spacing[2],\n        paddingHorizontal: theme.spacing[2],\n        borderRadius: theme.radii.md,\n      }}\n    >\n      <Text style={{ color: colors.foreground, fontSize: theme.fontSizes.sm }}>\n        {children}\n      </Text>\n    </Pressable>\n  );\n}\n\nexport const ContextMenu = DropdownMenu;\nexport const ContextMenuTrigger = DropdownMenuTrigger;\nexport const ContextMenuContent = DropdownMenuContent;\nexport const ContextMenuItem = DropdownMenuItem;\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "empty",
      "type": "registry:ui",
      "title": "Empty",
      "description": "React Native Empty for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/empty.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/empty.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  Text,\n  View,\n  type StyleProp,\n  type TextProps,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type EmptyVariant = \"chrome\" | \"outline\";\nexport type EmptyMediaVariant = \"default\" | \"icon\";\n\nexport interface EmptyProps extends ViewProps {\n  variant?: EmptyVariant;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Empty = forwardRef<View, EmptyProps>(\n  ({ variant = \"chrome\", children, style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flex: 1,\n            minWidth: 0,\n            flexDirection: \"column\",\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            gap: theme.spacing[6],\n            borderRadius: theme.radii[\"2xl\"],\n            padding: theme.spacing[6],\n            borderWidth: 1,\n            borderStyle: \"dashed\",\n            borderColor: colors.glassChromeBorder,\n            backgroundColor:\n              variant === \"chrome\" ? colors.glassChromeBgEnv : \"transparent\",\n          },\n          style,\n        )}\n        {...props}\n      >\n        {children}\n      </View>\n    );\n  },\n);\nEmpty.displayName = \"Empty\";\n\nexport const EmptyHeader = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            maxWidth: 320,\n            flexDirection: \"column\",\n            alignItems: \"center\",\n            gap: theme.spacing[2],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nEmptyHeader.displayName = \"EmptyHeader\";\n\nexport const EmptyTitle = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color: colors.foreground,\n            fontSize: theme.fontSizes.lg,\n            fontWeight: theme.fontWeights.semibold,\n            textAlign: \"center\",\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nEmptyTitle.displayName = \"EmptyTitle\";\n\nexport const EmptyDescription = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color: colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n            textAlign: \"center\",\n            lineHeight: theme.fontSizes.sm * theme.lineHeights.relaxed,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nEmptyDescription.displayName = \"EmptyDescription\";\n\nexport const EmptyContent = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flexDirection: \"column\",\n            alignItems: \"center\",\n            gap: theme.spacing[2],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nEmptyContent.displayName = \"EmptyContent\";\n\nexport interface EmptyMediaProps extends ViewProps {\n  variant?: EmptyMediaVariant;\n}\n\nexport const EmptyMedia = forwardRef<View, EmptyMediaProps>(\n  ({ variant = \"default\", style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            marginBottom: theme.spacing[2],\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            ...(variant === \"icon\"\n              ? {\n                  width: 48,\n                  height: 48,\n                  borderRadius: theme.radii.xl,\n                  backgroundColor: colors.glassChromeBgEnv,\n                  borderWidth: 1,\n                  borderColor: colors.glassChromeBorder,\n                }\n              : {}),\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nEmptyMedia.displayName = \"EmptyMedia\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "glass-bar",
      "type": "registry:ui",
      "title": "Glass Bar",
      "description": "React Native Glass Bar for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "glass-surface"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/glass-bar.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/glass-bar.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  View,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\nimport { GlassSurface } from \"./glass-surface\";\n\nexport interface GlassBarProps extends ViewProps {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const GlassBar = forwardRef<View, GlassBarProps>(\n  ({ children, style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <GlassSurface\n        ref={ref}\n        variant=\"chrome\"\n        style={cn(\n          {\n            flexDirection: \"row\",\n            alignItems: \"center\",\n            gap: theme.spacing[3],\n            paddingHorizontal: theme.spacing[3],\n            paddingVertical: theme.spacing[2],\n            borderRadius: theme.radii.full,\n            minHeight: 56,\n          },\n          style,\n        )}\n        {...props}\n      >\n        {children}\n      </GlassSurface>\n    );\n  },\n);\nGlassBar.displayName = \"GlassBar\";\n\nexport const GlassBarMedia = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            width: 40,\n            height: 40,\n            borderRadius: theme.radii.lg,\n            overflow: \"hidden\",\n            alignItems: \"center\",\n            justifyContent: \"center\",\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nGlassBarMedia.displayName = \"GlassBarMedia\";\n\nexport const GlassBarInfo = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => (\n    <View\n      ref={ref}\n      style={cn({ flex: 1, minWidth: 0, justifyContent: \"center\" }, style)}\n      {...props}\n    />\n  ),\n);\nGlassBarInfo.displayName = \"GlassBarInfo\";\n\nexport const GlassBarControls = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flexDirection: \"row\",\n            alignItems: \"center\",\n            gap: theme.spacing[1],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nGlassBarControls.displayName = \"GlassBarControls\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "glass-content-card",
      "type": "registry:ui",
      "title": "Glass Content Card",
      "description": "React Native Glass Content Card for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "glass-surface"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/glass-content-card.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/glass-content-card.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  View,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\nimport { GlassSurface } from \"./glass-surface\";\n\nexport interface GlassContentCardProps extends ViewProps {\n  gradient?: string;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const GlassContentCard = forwardRef<View, GlassContentCardProps>(\n  ({ gradient, children, style, ...props }, ref) => {\n    return (\n      <GlassSurface\n        ref={ref}\n        variant=\"content\"\n        contentBackground={gradient}\n        style={cn({ overflow: \"hidden\" }, style)}\n        {...props}\n      >\n        {children}\n      </GlassSurface>\n    );\n  },\n);\nGlassContentCard.displayName = \"GlassContentCard\";\n\nexport interface GlassContentPanelProps extends ViewProps {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const GlassContentPanel = forwardRef<View, GlassContentPanelProps>(\n  ({ children, style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            padding: theme.spacing[6],\n            gap: theme.spacing[2],\n          },\n          style,\n        )}\n        {...props}\n      >\n        {children}\n      </View>\n    );\n  },\n);\nGlassContentPanel.displayName = \"GlassContentPanel\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "glass-icon-button",
      "type": "registry:ui",
      "title": "Glass Icon Button",
      "description": "React Native Glass Icon Button for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/glass-icon-button.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/glass-icon-button.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  Animated,\n  Pressable,\n  Text,\n  type PressableProps,\n  type StyleProp,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { usePressScale } from \"../utils/animation\";\nimport { cn } from \"../utils/cn\";\nimport { pressedOpacity } from \"../utils/pressable\";\n\nexport type GlassIconButtonVariant = \"chrome\" | \"ghost\" | \"destructive\";\nexport type GlassIconButtonSize = \"sm\" | \"default\" | \"lg\";\n\nexport interface GlassIconButtonProps extends Omit<PressableProps, \"children\"> {\n  variant?: GlassIconButtonVariant;\n  size?: GlassIconButtonSize;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const GlassIconButton = forwardRef<\n  React.ElementRef<typeof Pressable>,\n  GlassIconButtonProps\n>(\n  (\n    {\n      variant = \"chrome\",\n      size = \"default\",\n      children,\n      disabled,\n      style,\n      onPressIn,\n      onPressOut,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const dim = size === \"sm\" ? 32 : size === \"lg\" ? 40 : 36;\n    const press = usePressScale({ pressedScale: 0.92, disabled: !!disabled });\n\n    const bg =\n      variant === \"ghost\"\n        ? \"transparent\"\n        : variant === \"destructive\"\n          ? colors.destructive\n          : colors.glassChromeBgEnv;\n\n    const fg =\n      variant === \"destructive\"\n        ? colors.destructiveForeground\n        : colors.glassChromeFg;\n\n    return (\n      <Animated.View style={press.style}>\n        <Pressable\n          ref={ref}\n          accessibilityRole=\"button\"\n          disabled={disabled}\n          onPressIn={(e) => {\n            press.onPressIn();\n            onPressIn?.(e);\n          }}\n          onPressOut={(e) => {\n            press.onPressOut();\n            onPressOut?.(e);\n          }}\n          style={({ pressed }) =>\n            cn(\n              {\n                width: dim,\n                height: dim,\n                borderRadius: theme.radii.full,\n                alignItems: \"center\",\n                justifyContent: \"center\",\n                backgroundColor: bg,\n                borderWidth: variant === \"ghost\" ? 0 : 1,\n                borderColor: colors.glassChromeBorder,\n                opacity: pressedOpacity(pressed) * (disabled ? 0.5 : 1),\n              },\n              style,\n            )\n          }\n          {...props}\n        >\n          {typeof children === \"string\" ? (\n            <Text style={{ color: fg, fontSize: dim * 0.4 }}>{children}</Text>\n          ) : (\n            children\n          )}\n        </Pressable>\n      </Animated.View>\n    );\n  },\n);\nGlassIconButton.displayName = \"GlassIconButton\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "glass-surface",
      "type": "registry:ui",
      "title": "Glass Surface",
      "description": "React Native Glass Surface for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/glass-surface.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/glass-surface.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  Platform,\n  StyleSheet,\n  View,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type GlassSurfaceVariant =\n  | \"chrome\"\n  | \"elevated\"\n  | \"content\"\n  | \"outline\"\n  | \"panel\"\n  | \"field\"\n  | \"button\";\n\nexport interface GlassSurfaceProps extends ViewProps {\n  variant?: GlassSurfaceVariant;\n  /** Prefer blur when expo-blur is available. Default true. */\n  blur?: boolean;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n  contentStyle?: StyleProp<ViewStyle>;\n  /** Optional solid content gradient fill for content cards. */\n  contentBackground?: string;\n}\n\n/**\n * Shared glass surface. Uses translucent fills by default.\n * When `expo-blur` is installed, chrome/panel variants can wrap BlurView\n * (resolved lazily so the package remains optional).\n */\nexport const GlassSurface = forwardRef<View, GlassSurfaceProps>(\n  (\n    {\n      variant = \"chrome\",\n      blur = true,\n      children,\n      style,\n      contentStyle,\n      contentBackground,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const radius =\n      variant === \"content\" ? theme.radii[\"3xl\"] : theme.radii[\"2xl\"];\n\n    const base: ViewStyle = {\n      borderRadius: radius,\n      overflow: \"hidden\",\n      borderWidth: StyleSheet.hairlineWidth * 2,\n      borderColor: colors.glassChromeBorder,\n      ...Platform.select({\n        ios: {\n          shadowColor: \"#000\",\n          shadowOffset: { width: 0, height: 4 },\n          shadowOpacity: 0.12,\n          shadowRadius: 12,\n        },\n        android: { elevation: 3 },\n        default: {},\n      }),\n    };\n\n    const byVariant: Record<GlassSurfaceVariant, ViewStyle> = {\n      chrome: {\n        backgroundColor: colors.glassChromeBgEnv,\n      },\n      elevated: {\n        backgroundColor: colors.glassChromeBg,\n      },\n      content: {\n        backgroundColor: contentBackground ?? colors.primary,\n        borderColor: \"rgba(0,0,0,0.1)\",\n      },\n      outline: {\n        backgroundColor: colors.glassSurfaceFill,\n        borderColor: colors.glassChromeBorder,\n      },\n      panel: {\n        backgroundColor: colors.glassChromeBgEnv,\n      },\n      field: {\n        backgroundColor: colors.glassChromeBgEnv,\n        borderRadius: theme.radii.xl,\n      },\n      button: {\n        backgroundColor: colors.glassButtonUiBg,\n        borderColor: colors.glassButtonUiBorder,\n      },\n    };\n\n    const BlurView = blur ? tryGetBlurView() : null;\n\n    if (BlurView && (variant === \"chrome\" || variant === \"panel\" || variant === \"elevated\")) {\n      return (\n        <View ref={ref} style={cn(base, byVariant[variant], style)} {...props}>\n          <BlurView\n            intensity={40}\n            tint={theme.mode === \"dark\" ? \"dark\" : \"light\"}\n            style={StyleSheet.absoluteFill}\n          />\n          <View style={cn({ flex: 1 }, contentStyle)}>{children}</View>\n        </View>\n      );\n    }\n\n    return (\n      <View\n        ref={ref}\n        style={cn(base, byVariant[variant], style)}\n        {...props}\n      >\n        {children}\n      </View>\n    );\n  },\n);\nGlassSurface.displayName = \"GlassSurface\";\n\ntype BlurViewComponent = React.ComponentType<{\n  intensity?: number;\n  tint?: \"light\" | \"dark\" | \"default\";\n  style?: StyleProp<ViewStyle>;\n  children?: ReactNode;\n}>;\n\nfunction tryGetBlurView(): BlurViewComponent | null {\n  try {\n    // Optional peer — not required for the package to load.\n    // eslint-disable-next-line @typescript-eslint/no-require-imports\n    const mod = require(\"expo-blur\") as { BlurView?: BlurViewComponent };\n    return mod.BlurView ?? null;\n  } catch {\n    return null;\n  }\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "hover-card",
      "type": "registry:ui",
      "title": "Hover Card",
      "description": "React Native Hover Card for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "popover"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/hover-card.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/hover-card.tsx",
          "content": "export {\n  Popover as HoverCard,\n  PopoverTrigger as HoverCardTrigger,\n  PopoverContent as HoverCardContent,\n} from \"./popover\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "input",
      "type": "registry:ui",
      "title": "Input",
      "description": "React Native Input for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/input.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/input.tsx",
          "content": "import { forwardRef } from \"react\";\nimport {\n  TextInput,\n  type StyleProp,\n  type TextInputProps,\n  type TextStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type FieldVariant = \"chrome\" | \"outline\";\nexport type FieldSize = \"sm\" | \"default\" | \"lg\";\nexport type FieldState = \"default\" | \"error\" | \"success\";\n\nexport interface InputProps extends TextInputProps {\n  variant?: FieldVariant;\n  size?: FieldSize;\n  state?: FieldState;\n  style?: StyleProp<TextStyle>;\n}\n\nexport const Input = forwardRef<TextInput, InputProps>(\n  (\n    {\n      variant = \"chrome\",\n      size = \"default\",\n      state = \"default\",\n      style,\n      placeholderTextColor,\n      editable = true,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const height = size === \"sm\" ? 36 : size === \"lg\" ? 44 : 40;\n    const fontSize =\n      size === \"sm\"\n        ? theme.fontSizes.xs\n        : size === \"lg\"\n          ? theme.fontSizes.base\n          : theme.fontSizes.sm;\n\n    const borderColor =\n      state === \"error\"\n        ? colors.destructive\n        : state === \"success\"\n          ? colors.success\n          : colors.glassChromeBorder;\n\n    return (\n      <TextInput\n        ref={ref}\n        editable={editable}\n        placeholderTextColor={\n          placeholderTextColor ?? colors.glassChromeFgMuted\n        }\n        style={cn(\n          {\n            width: \"100%\",\n            height,\n            borderRadius: theme.radii.xl,\n            paddingHorizontal: size === \"lg\" ? theme.spacing[4] : theme.spacing[3],\n            fontSize,\n            color: colors.glassChromeFg,\n            backgroundColor:\n              variant === \"outline\"\n                ? colors.glassSurfaceFill\n                : colors.glassChromeBgEnv,\n            borderWidth: 1,\n            borderColor,\n            opacity: editable === false ? 0.5 : 1,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nInput.displayName = \"Input\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "kbd",
      "type": "registry:ui",
      "title": "Kbd",
      "description": "React Native Kbd for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "badge"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/kbd.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/kbd.tsx",
          "content": "import { Badge, type BadgeProps } from \"./badge\";\n\nexport type KbdProps = BadgeProps;\n\nexport function Kbd(props: KbdProps) {\n  return <Badge variant=\"outline\" size=\"sm\" {...props} />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "label",
      "type": "registry:ui",
      "title": "Label",
      "description": "React Native Label for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/label.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/label.tsx",
          "content": "import { forwardRef } from \"react\";\nimport { Text, type TextProps } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type LabelVariant = \"default\" | \"chrome\" | \"muted\";\n\nexport interface LabelProps extends TextProps {\n  variant?: LabelVariant;\n  required?: boolean;\n}\n\nexport const Label = forwardRef<Text, LabelProps>(\n  ({ variant = \"default\", required, style, children, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    const color =\n      variant === \"muted\"\n        ? colors.mutedForeground\n        : variant === \"chrome\"\n          ? colors.glassChromeFg\n          : colors.foreground;\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            fontSize: theme.fontSizes.sm,\n            fontWeight: theme.fontWeights.medium,\n            color,\n            marginBottom: theme.spacing[1],\n          },\n          style,\n        )}\n        {...props}\n      >\n        {children}\n        {required ? (\n          <Text style={{ color: colors.destructive }}> *</Text>\n        ) : null}\n      </Text>\n    );\n  },\n);\nLabel.displayName = \"Label\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "layout",
      "type": "registry:ui",
      "title": "Layout",
      "description": "React Native Layout for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/layout.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/layout.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { View, type ViewProps, type ViewStyle } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport function Stack({\n  gap = 3,\n  children,\n  style,\n  ...props\n}: ViewProps & { gap?: number; children?: ReactNode }) {\n  const { theme } = useTheme();\n  const g = theme.spacing[gap as keyof typeof theme.spacing] ?? gap;\n  return (\n    <View style={[{ gap: g }, style]} {...props}>\n      {children}\n    </View>\n  );\n}\n\nexport function Cluster({\n  gap = 2,\n  children,\n  style,\n  ...props\n}: ViewProps & { gap?: number; children?: ReactNode }) {\n  const { theme } = useTheme();\n  const g = theme.spacing[gap as keyof typeof theme.spacing] ?? gap;\n  return (\n    <View\n      style={[{ flexDirection: \"row\", flexWrap: \"wrap\", gap: g, alignItems: \"center\" }, style]}\n      {...props}\n    >\n      {children}\n    </View>\n  );\n}\n\nexport function Split({\n  children,\n  style,\n}: {\n  children?: ReactNode;\n  style?: ViewStyle;\n}) {\n  return (\n    <View style={[{ flexDirection: \"row\", gap: 12, alignItems: \"center\" }, style]}>\n      {children}\n    </View>\n  );\n}\n\nexport function Layout(props: ViewProps) {\n  return <View {...props} />;\n}\n\nexport function Resizable({\n  children,\n}: {\n  children?: ReactNode;\n}) {\n  return <View style={{ flexDirection: \"row\", minHeight: 120 }}>{children}</View>;\n}\n\nexport function BackgroundPicturePicker({\n  onSelect,\n}: {\n  onSelect?: (id: string) => void;\n}) {\n  const { theme, colors } = useTheme();\n  const presets = [\"mesh\", \"dawn\", \"night\"];\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {presets.map((id) => (\n        <View\n          key={id}\n          onTouchEnd={() => onSelect?.(id)}\n          style={{\n            flex: 1,\n            height: 56,\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n            borderWidth: 1,\n            borderColor: colors.glassChromeBorder,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "resizable",
      "type": "registry:ui",
      "title": "Resizable",
      "description": "React Native Resizable for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/layout.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/layout.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { View, type ViewProps, type ViewStyle } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport function Stack({\n  gap = 3,\n  children,\n  style,\n  ...props\n}: ViewProps & { gap?: number; children?: ReactNode }) {\n  const { theme } = useTheme();\n  const g = theme.spacing[gap as keyof typeof theme.spacing] ?? gap;\n  return (\n    <View style={[{ gap: g }, style]} {...props}>\n      {children}\n    </View>\n  );\n}\n\nexport function Cluster({\n  gap = 2,\n  children,\n  style,\n  ...props\n}: ViewProps & { gap?: number; children?: ReactNode }) {\n  const { theme } = useTheme();\n  const g = theme.spacing[gap as keyof typeof theme.spacing] ?? gap;\n  return (\n    <View\n      style={[{ flexDirection: \"row\", flexWrap: \"wrap\", gap: g, alignItems: \"center\" }, style]}\n      {...props}\n    >\n      {children}\n    </View>\n  );\n}\n\nexport function Split({\n  children,\n  style,\n}: {\n  children?: ReactNode;\n  style?: ViewStyle;\n}) {\n  return (\n    <View style={[{ flexDirection: \"row\", gap: 12, alignItems: \"center\" }, style]}>\n      {children}\n    </View>\n  );\n}\n\nexport function Layout(props: ViewProps) {\n  return <View {...props} />;\n}\n\nexport function Resizable({\n  children,\n}: {\n  children?: ReactNode;\n}) {\n  return <View style={{ flexDirection: \"row\", minHeight: 120 }}>{children}</View>;\n}\n\nexport function BackgroundPicturePicker({\n  onSelect,\n}: {\n  onSelect?: (id: string) => void;\n}) {\n  const { theme, colors } = useTheme();\n  const presets = [\"mesh\", \"dawn\", \"night\"];\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {presets.map((id) => (\n        <View\n          key={id}\n          onTouchEnd={() => onSelect?.(id)}\n          style={{\n            flex: 1,\n            height: 56,\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n            borderWidth: 1,\n            borderColor: colors.glassChromeBorder,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "background-picture-picker",
      "type": "registry:ui",
      "title": "Background Picture Picker",
      "description": "React Native Background Picture Picker for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/layout.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/layout.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { View, type ViewProps, type ViewStyle } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport function Stack({\n  gap = 3,\n  children,\n  style,\n  ...props\n}: ViewProps & { gap?: number; children?: ReactNode }) {\n  const { theme } = useTheme();\n  const g = theme.spacing[gap as keyof typeof theme.spacing] ?? gap;\n  return (\n    <View style={[{ gap: g }, style]} {...props}>\n      {children}\n    </View>\n  );\n}\n\nexport function Cluster({\n  gap = 2,\n  children,\n  style,\n  ...props\n}: ViewProps & { gap?: number; children?: ReactNode }) {\n  const { theme } = useTheme();\n  const g = theme.spacing[gap as keyof typeof theme.spacing] ?? gap;\n  return (\n    <View\n      style={[{ flexDirection: \"row\", flexWrap: \"wrap\", gap: g, alignItems: \"center\" }, style]}\n      {...props}\n    >\n      {children}\n    </View>\n  );\n}\n\nexport function Split({\n  children,\n  style,\n}: {\n  children?: ReactNode;\n  style?: ViewStyle;\n}) {\n  return (\n    <View style={[{ flexDirection: \"row\", gap: 12, alignItems: \"center\" }, style]}>\n      {children}\n    </View>\n  );\n}\n\nexport function Layout(props: ViewProps) {\n  return <View {...props} />;\n}\n\nexport function Resizable({\n  children,\n}: {\n  children?: ReactNode;\n}) {\n  return <View style={{ flexDirection: \"row\", minHeight: 120 }}>{children}</View>;\n}\n\nexport function BackgroundPicturePicker({\n  onSelect,\n}: {\n  onSelect?: (id: string) => void;\n}) {\n  const { theme, colors } = useTheme();\n  const presets = [\"mesh\", \"dawn\", \"night\"];\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {presets.map((id) => (\n        <View\n          key={id}\n          onTouchEnd={() => onSelect?.(id)}\n          style={{\n            flex: 1,\n            height: 56,\n            borderRadius: theme.radii.lg,\n            backgroundColor: colors.glassSurfaceFill,\n            borderWidth: 1,\n            borderColor: colors.glassChromeBorder,\n          }}\n        />\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "link",
      "type": "registry:ui",
      "title": "Link",
      "description": "React Native Link for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/link.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/link.tsx",
          "content": "import { Linking, Text, type TextProps } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport interface LinkProps extends TextProps {\n  href: string;\n}\n\nexport function Link({ href, style, ...props }: LinkProps) {\n  const { colors, theme } = useTheme();\n  return (\n    <Text\n      accessibilityRole=\"link\"\n      onPress={() => {\n        void Linking.openURL(href);\n      }}\n      style={cn(\n        {\n          color: colors.primary,\n          fontSize: theme.fontSizes.sm,\n          textDecorationLine: \"underline\",\n        },\n        style,\n      )}\n      {...props}\n    />\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "loading-screen",
      "type": "registry:ui",
      "title": "Loading Screen",
      "description": "React Native Loading Screen for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "spinner"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/loading-screen.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/loading-screen.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Spinner } from \"./spinner\";\n\nexport function LoadingScreen({ label = \"Loading\" }: { label?: string }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        flex: 1,\n        minHeight: 180,\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        gap: theme.spacing[3],\n      }}\n    >\n      <Spinner />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {label}\n      </Text>\n    </View>\n  );\n}\n\nexport function RetryView({\n  title = \"Something went wrong\",\n  onRetry,\n}: {\n  title?: string;\n  onRetry?: () => void;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        alignItems: \"center\",\n        gap: theme.spacing[3],\n        padding: theme.spacing[6],\n      }}\n    >\n      <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.semibold }}>\n        {title}\n      </Text>\n      <Text\n        onPress={onRetry}\n        style={{ color: colors.primary, fontSize: theme.fontSizes.sm }}\n      >\n        Try again\n      </Text>\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "retry-view",
      "type": "registry:ui",
      "title": "Retry View",
      "description": "React Native Retry View for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "spinner"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/loading-screen.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/loading-screen.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Spinner } from \"./spinner\";\n\nexport function LoadingScreen({ label = \"Loading\" }: { label?: string }) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        flex: 1,\n        minHeight: 180,\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        gap: theme.spacing[3],\n      }}\n    >\n      <Spinner />\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        {label}\n      </Text>\n    </View>\n  );\n}\n\nexport function RetryView({\n  title = \"Something went wrong\",\n  onRetry,\n}: {\n  title?: string;\n  onRetry?: () => void;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View\n      style={{\n        alignItems: \"center\",\n        gap: theme.spacing[3],\n        padding: theme.spacing[6],\n      }}\n    >\n      <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.semibold }}>\n        {title}\n      </Text>\n      <Text\n        onPress={onRetry}\n        style={{ color: colors.primary, fontSize: theme.fontSizes.sm }}\n      >\n        Try again\n      </Text>\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "markdown-viewer",
      "type": "registry:ui",
      "title": "Markdown Viewer",
      "description": "React Native Markdown Viewer for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/markdown-viewer.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/markdown-viewer.tsx",
          "content": "import { useMemo } from \"react\";\nimport {\n  Text,\n  View,\n  type StyleProp,\n  type TextStyle,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport interface MarkdownViewerProps {\n  /** Markdown source string. */\n  children?: string;\n  content?: string;\n  style?: StyleProp<ViewStyle>;\n}\n\ntype Block =\n  | { type: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"p\" | \"blockquote\" | \"code\"; text: string }\n  | { type: \"ul\" | \"ol\"; items: string[] }\n  | { type: \"hr\" };\n\nfunction parseMarkdown(src: string): Block[] {\n  const lines = src.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n  const blocks: Block[] = [];\n  let i = 0;\n\n  while (i < lines.length) {\n    const line = lines[i] ?? \"\";\n    if (!line.trim()) {\n      i++;\n      continue;\n    }\n    if (line.startsWith(\"```\")) {\n      const buf: string[] = [];\n      i++;\n      while (i < lines.length && !(lines[i] ?? \"\").startsWith(\"```\")) {\n        buf.push(lines[i] ?? \"\");\n        i++;\n      }\n      i++;\n      blocks.push({ type: \"code\", text: buf.join(\"\\n\") });\n      continue;\n    }\n    if (/^#{1,4}\\s/.test(line)) {\n      const level = (line.match(/^#+/)?.[0].length ?? 1) as 1 | 2 | 3 | 4;\n      const text = line.replace(/^#{1,4}\\s+/, \"\");\n      blocks.push({\n        type: (`h${Math.min(level, 4)}` as \"h1\" | \"h2\" | \"h3\" | \"h4\"),\n        text,\n      });\n      i++;\n      continue;\n    }\n    if (line.startsWith(\"> \")) {\n      blocks.push({ type: \"blockquote\", text: line.slice(2) });\n      i++;\n      continue;\n    }\n    if (/^[-*]\\s+/.test(line)) {\n      const items: string[] = [];\n      while (i < lines.length && /^[-*]\\s+/.test(lines[i] ?? \"\")) {\n        items.push((lines[i] ?? \"\").replace(/^[-*]\\s+/, \"\"));\n        i++;\n      }\n      blocks.push({ type: \"ul\", items });\n      continue;\n    }\n    if (/^\\d+\\.\\s+/.test(line)) {\n      const items: string[] = [];\n      while (i < lines.length && /^\\d+\\.\\s+/.test(lines[i] ?? \"\")) {\n        items.push((lines[i] ?? \"\").replace(/^\\d+\\.\\s+/, \"\"));\n        i++;\n      }\n      blocks.push({ type: \"ol\", items });\n      continue;\n    }\n    if (/^---+$/.test(line.trim())) {\n      blocks.push({ type: \"hr\" });\n      i++;\n      continue;\n    }\n    blocks.push({ type: \"p\", text: line });\n    i++;\n  }\n  return blocks;\n}\n\n/** Lightweight markdown renderer (headings, lists, code, quotes). No external dep. */\nexport function MarkdownViewer({\n  children,\n  content,\n  style,\n}: MarkdownViewerProps) {\n  const { theme, colors } = useTheme();\n  const src = content ?? children ?? \"\";\n  const blocks = useMemo(() => parseMarkdown(src), [src]);\n\n  const baseText: TextStyle = {\n    color: colors.foreground,\n    fontSize: theme.fontSizes.base,\n    lineHeight: theme.fontSizes.base * theme.lineHeights.relaxed,\n  };\n\n  const headingSizes: Record<\"h1\" | \"h2\" | \"h3\" | \"h4\", number> = {\n    h1: theme.fontSizes[\"3xl\"],\n    h2: theme.fontSizes[\"2xl\"],\n    h3: theme.fontSizes.xl,\n    h4: theme.fontSizes.lg,\n  };\n\n  return (\n    <View style={cn({ gap: theme.spacing[3] }, style)}>\n      {blocks.map((block, idx) => {\n        switch (block.type) {\n          case \"hr\":\n            return (\n              <View\n                key={idx}\n                style={{\n                  height: 1,\n                  backgroundColor: colors.border,\n                  marginVertical: theme.spacing[2],\n                }}\n              />\n            );\n          case \"code\":\n            return (\n              <View\n                key={idx}\n                style={{\n                  backgroundColor: colors.muted,\n                  borderRadius: theme.radii.lg,\n                  padding: theme.spacing[3],\n                  borderWidth: 1,\n                  borderColor: colors.border,\n                }}\n              >\n                <Text\n                  style={{\n                    fontFamily: \"Menlo\",\n                    fontSize: theme.fontSizes.sm,\n                    color: colors.foreground,\n                  }}\n                >\n                  {block.text}\n                </Text>\n              </View>\n            );\n          case \"ul\":\n          case \"ol\":\n            return (\n              <View key={idx} style={{ gap: 4, paddingLeft: theme.spacing[2] }}>\n                {block.items.map((item, j) => (\n                  <Text key={j} style={baseText}>\n                    {block.type === \"ul\" ? \"• \" : `${j + 1}. `}\n                    {item}\n                  </Text>\n                ))}\n              </View>\n            );\n          case \"blockquote\":\n            return (\n              <View\n                key={idx}\n                style={{\n                  borderLeftWidth: 3,\n                  borderLeftColor: colors.border,\n                  paddingLeft: theme.spacing[3],\n                }}\n              >\n                <Text\n                  style={{\n                    ...baseText,\n                    fontStyle: \"italic\",\n                    color: colors.mutedForeground,\n                  }}\n                >\n                  {block.text}\n                </Text>\n              </View>\n            );\n          case \"h1\":\n          case \"h2\":\n          case \"h3\":\n          case \"h4\": {\n            const size = headingSizes[block.type];\n            return (\n              <Text\n                key={idx}\n                style={{\n                  ...baseText,\n                  fontSize: size,\n                  fontWeight: theme.fontWeights.semibold,\n                  lineHeight: size * theme.lineHeights.snug,\n                }}\n              >\n                {block.text}\n              </Text>\n            );\n          }\n          case \"p\":\n          default:\n            return (\n              <Text key={idx} style={baseText}>\n                {\"text\" in block ? block.text : \"\"}\n              </Text>\n            );\n        }\n      })}\n    </View>\n  );\n}\n\nexport function MarkdownCodeBlock({\n  children,\n  style,\n}: {\n  children?: string;\n  style?: StyleProp<ViewStyle>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={cn(\n        {\n          backgroundColor: colors.muted,\n          borderRadius: theme.radii.lg,\n          padding: theme.spacing[3],\n          borderWidth: 1,\n          borderColor: colors.border,\n        },\n        style,\n      )}\n    >\n      <Text\n        style={{\n          fontFamily: \"Menlo\",\n          fontSize: theme.fontSizes.sm,\n          color: colors.foreground,\n        }}\n      >\n        {children}\n      </Text>\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "aspect-ratio",
      "type": "registry:ui",
      "title": "Aspect Ratio",
      "description": "React Native Aspect Ratio for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "button",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/media.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/media.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Image, Text, View, type ImageSourcePropType } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Button } from \"./button\";\nimport { Progress } from \"./progress\";\n\nexport function AspectRatio({\n  ratio = 16 / 9,\n  children,\n}: {\n  ratio?: number;\n  children?: ReactNode;\n}) {\n  return (\n    <View style={{ width: \"100%\", aspectRatio: ratio, overflow: \"hidden\" }}>\n      {children}\n    </View>\n  );\n}\n\nexport function ImagePreview({\n  source,\n}: {\n  source: ImageSourcePropType | string;\n}) {\n  const src = typeof source === \"string\" ? { uri: source } : source;\n  return (\n    <AspectRatio>\n      <Image source={src} style={{ width: \"100%\", height: \"100%\" }} />\n    </AspectRatio>\n  );\n}\n\nexport function ImageEditor({ source }: { source: ImageSourcePropType | string }) {\n  return <ImagePreview source={source} />;\n}\n\nexport function MediaPlayer({\n  title = \"Track\",\n  progress = 35,\n}: {\n  title?: string;\n  progress?: number;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.semibold }}>\n        {title}\n      </Text>\n      <Progress value={progress} />\n      <Button variant=\"primary\">Play</Button>\n    </View>\n  );\n}\n\nexport function FileUpload({\n  label = \"Choose file\",\n  onPress,\n}: {\n  label?: string;\n  onPress?: () => void;\n}) {\n  return (\n    <Button variant=\"outline\" onPress={onPress}>\n      {label}\n    </Button>\n  );\n}\n\nexport function FontPicker({\n  value,\n  options = [\"System\", \"Serif\", \"Mono\"],\n  onChange,\n}: {\n  value?: string;\n  options?: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "image-preview",
      "type": "registry:ui",
      "title": "Image Preview",
      "description": "React Native Image Preview for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "button",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/media.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/media.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Image, Text, View, type ImageSourcePropType } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Button } from \"./button\";\nimport { Progress } from \"./progress\";\n\nexport function AspectRatio({\n  ratio = 16 / 9,\n  children,\n}: {\n  ratio?: number;\n  children?: ReactNode;\n}) {\n  return (\n    <View style={{ width: \"100%\", aspectRatio: ratio, overflow: \"hidden\" }}>\n      {children}\n    </View>\n  );\n}\n\nexport function ImagePreview({\n  source,\n}: {\n  source: ImageSourcePropType | string;\n}) {\n  const src = typeof source === \"string\" ? { uri: source } : source;\n  return (\n    <AspectRatio>\n      <Image source={src} style={{ width: \"100%\", height: \"100%\" }} />\n    </AspectRatio>\n  );\n}\n\nexport function ImageEditor({ source }: { source: ImageSourcePropType | string }) {\n  return <ImagePreview source={source} />;\n}\n\nexport function MediaPlayer({\n  title = \"Track\",\n  progress = 35,\n}: {\n  title?: string;\n  progress?: number;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.semibold }}>\n        {title}\n      </Text>\n      <Progress value={progress} />\n      <Button variant=\"primary\">Play</Button>\n    </View>\n  );\n}\n\nexport function FileUpload({\n  label = \"Choose file\",\n  onPress,\n}: {\n  label?: string;\n  onPress?: () => void;\n}) {\n  return (\n    <Button variant=\"outline\" onPress={onPress}>\n      {label}\n    </Button>\n  );\n}\n\nexport function FontPicker({\n  value,\n  options = [\"System\", \"Serif\", \"Mono\"],\n  onChange,\n}: {\n  value?: string;\n  options?: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "image-editor",
      "type": "registry:ui",
      "title": "Image Editor",
      "description": "React Native Image Editor for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "button",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/media.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/media.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Image, Text, View, type ImageSourcePropType } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Button } from \"./button\";\nimport { Progress } from \"./progress\";\n\nexport function AspectRatio({\n  ratio = 16 / 9,\n  children,\n}: {\n  ratio?: number;\n  children?: ReactNode;\n}) {\n  return (\n    <View style={{ width: \"100%\", aspectRatio: ratio, overflow: \"hidden\" }}>\n      {children}\n    </View>\n  );\n}\n\nexport function ImagePreview({\n  source,\n}: {\n  source: ImageSourcePropType | string;\n}) {\n  const src = typeof source === \"string\" ? { uri: source } : source;\n  return (\n    <AspectRatio>\n      <Image source={src} style={{ width: \"100%\", height: \"100%\" }} />\n    </AspectRatio>\n  );\n}\n\nexport function ImageEditor({ source }: { source: ImageSourcePropType | string }) {\n  return <ImagePreview source={source} />;\n}\n\nexport function MediaPlayer({\n  title = \"Track\",\n  progress = 35,\n}: {\n  title?: string;\n  progress?: number;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.semibold }}>\n        {title}\n      </Text>\n      <Progress value={progress} />\n      <Button variant=\"primary\">Play</Button>\n    </View>\n  );\n}\n\nexport function FileUpload({\n  label = \"Choose file\",\n  onPress,\n}: {\n  label?: string;\n  onPress?: () => void;\n}) {\n  return (\n    <Button variant=\"outline\" onPress={onPress}>\n      {label}\n    </Button>\n  );\n}\n\nexport function FontPicker({\n  value,\n  options = [\"System\", \"Serif\", \"Mono\"],\n  onChange,\n}: {\n  value?: string;\n  options?: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "media-player",
      "type": "registry:ui",
      "title": "Media Player",
      "description": "React Native Media Player for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "button",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/media.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/media.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Image, Text, View, type ImageSourcePropType } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Button } from \"./button\";\nimport { Progress } from \"./progress\";\n\nexport function AspectRatio({\n  ratio = 16 / 9,\n  children,\n}: {\n  ratio?: number;\n  children?: ReactNode;\n}) {\n  return (\n    <View style={{ width: \"100%\", aspectRatio: ratio, overflow: \"hidden\" }}>\n      {children}\n    </View>\n  );\n}\n\nexport function ImagePreview({\n  source,\n}: {\n  source: ImageSourcePropType | string;\n}) {\n  const src = typeof source === \"string\" ? { uri: source } : source;\n  return (\n    <AspectRatio>\n      <Image source={src} style={{ width: \"100%\", height: \"100%\" }} />\n    </AspectRatio>\n  );\n}\n\nexport function ImageEditor({ source }: { source: ImageSourcePropType | string }) {\n  return <ImagePreview source={source} />;\n}\n\nexport function MediaPlayer({\n  title = \"Track\",\n  progress = 35,\n}: {\n  title?: string;\n  progress?: number;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.semibold }}>\n        {title}\n      </Text>\n      <Progress value={progress} />\n      <Button variant=\"primary\">Play</Button>\n    </View>\n  );\n}\n\nexport function FileUpload({\n  label = \"Choose file\",\n  onPress,\n}: {\n  label?: string;\n  onPress?: () => void;\n}) {\n  return (\n    <Button variant=\"outline\" onPress={onPress}>\n      {label}\n    </Button>\n  );\n}\n\nexport function FontPicker({\n  value,\n  options = [\"System\", \"Serif\", \"Mono\"],\n  onChange,\n}: {\n  value?: string;\n  options?: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "file-upload",
      "type": "registry:ui",
      "title": "File Upload",
      "description": "React Native File Upload for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "button",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/media.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/media.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Image, Text, View, type ImageSourcePropType } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Button } from \"./button\";\nimport { Progress } from \"./progress\";\n\nexport function AspectRatio({\n  ratio = 16 / 9,\n  children,\n}: {\n  ratio?: number;\n  children?: ReactNode;\n}) {\n  return (\n    <View style={{ width: \"100%\", aspectRatio: ratio, overflow: \"hidden\" }}>\n      {children}\n    </View>\n  );\n}\n\nexport function ImagePreview({\n  source,\n}: {\n  source: ImageSourcePropType | string;\n}) {\n  const src = typeof source === \"string\" ? { uri: source } : source;\n  return (\n    <AspectRatio>\n      <Image source={src} style={{ width: \"100%\", height: \"100%\" }} />\n    </AspectRatio>\n  );\n}\n\nexport function ImageEditor({ source }: { source: ImageSourcePropType | string }) {\n  return <ImagePreview source={source} />;\n}\n\nexport function MediaPlayer({\n  title = \"Track\",\n  progress = 35,\n}: {\n  title?: string;\n  progress?: number;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.semibold }}>\n        {title}\n      </Text>\n      <Progress value={progress} />\n      <Button variant=\"primary\">Play</Button>\n    </View>\n  );\n}\n\nexport function FileUpload({\n  label = \"Choose file\",\n  onPress,\n}: {\n  label?: string;\n  onPress?: () => void;\n}) {\n  return (\n    <Button variant=\"outline\" onPress={onPress}>\n      {label}\n    </Button>\n  );\n}\n\nexport function FontPicker({\n  value,\n  options = [\"System\", \"Serif\", \"Mono\"],\n  onChange,\n}: {\n  value?: string;\n  options?: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "font-picker",
      "type": "registry:ui",
      "title": "Font Picker",
      "description": "React Native Font Picker for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "button",
        "progress"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/media.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/media.tsx",
          "content": "import type { ReactNode } from \"react\";\nimport { Image, Text, View, type ImageSourcePropType } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Button } from \"./button\";\nimport { Progress } from \"./progress\";\n\nexport function AspectRatio({\n  ratio = 16 / 9,\n  children,\n}: {\n  ratio?: number;\n  children?: ReactNode;\n}) {\n  return (\n    <View style={{ width: \"100%\", aspectRatio: ratio, overflow: \"hidden\" }}>\n      {children}\n    </View>\n  );\n}\n\nexport function ImagePreview({\n  source,\n}: {\n  source: ImageSourcePropType | string;\n}) {\n  const src = typeof source === \"string\" ? { uri: source } : source;\n  return (\n    <AspectRatio>\n      <Image source={src} style={{ width: \"100%\", height: \"100%\" }} />\n    </AspectRatio>\n  );\n}\n\nexport function ImageEditor({ source }: { source: ImageSourcePropType | string }) {\n  return <ImagePreview source={source} />;\n}\n\nexport function MediaPlayer({\n  title = \"Track\",\n  progress = 35,\n}: {\n  title?: string;\n  progress?: number;\n}) {\n  const { colors, theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[3] }}>\n      <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.semibold }}>\n        {title}\n      </Text>\n      <Progress value={progress} />\n      <Button variant=\"primary\">Play</Button>\n    </View>\n  );\n}\n\nexport function FileUpload({\n  label = \"Choose file\",\n  onPress,\n}: {\n  label?: string;\n  onPress?: () => void;\n}) {\n  return (\n    <Button variant=\"outline\" onPress={onPress}>\n      {label}\n    </Button>\n  );\n}\n\nexport function FontPicker({\n  value,\n  options = [\"System\", \"Serif\", \"Mono\"],\n  onChange,\n}: {\n  value?: string;\n  options?: string[];\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {options.map((o) => (\n        <Button\n          key={o}\n          variant={o === value ? \"primary\" : \"outline\"}\n          onPress={() => onChange?.(o)}\n        >\n          {o}\n        </Button>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "native-select",
      "type": "registry:ui",
      "title": "Native Select",
      "description": "React Native Native Select for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "select"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/native-select.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/native-select.tsx",
          "content": "export {\n  Select as NativeSelect,\n  SelectTrigger as NativeSelectTrigger,\n  SelectValue as NativeSelectValue,\n  SelectContent as NativeSelectContent,\n  SelectItem as NativeSelectItem,\n} from \"./select\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "number-input",
      "type": "registry:ui",
      "title": "Number Input",
      "description": "React Native Number Input for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/number-input.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/number-input.tsx",
          "content": "import { Input, type InputProps } from \"./input\";\n\nexport interface NumberInputProps extends Omit<InputProps, \"keyboardType\" | \"value\" | \"onChangeText\"> {\n  value?: number;\n  onValueChange?: (value: number | undefined) => void;\n  prefix?: string;\n}\n\nexport function NumberInput({\n  value,\n  onValueChange,\n  prefix,\n  ...props\n}: NumberInputProps) {\n  return (\n    <Input\n      keyboardType=\"decimal-pad\"\n      value={\n        value === undefined || Number.isNaN(value)\n          ? \"\"\n          : `${prefix ?? \"\"}${value}`\n      }\n      onChangeText={(t) => {\n        const raw = t.replace(/[^\\d.-]/g, \"\");\n        if (raw === \"\" || raw === \"-\") {\n          onValueChange?.(undefined);\n          return;\n        }\n        onValueChange?.(Number(raw));\n      }}\n      {...props}\n    />\n  );\n}\n\nexport type CurrencyInputProps = NumberInputProps;\n\nexport function CurrencyInput({ prefix = \"$\", ...props }: CurrencyInputProps) {\n  return <NumberInput prefix={prefix} {...props} />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "currency-input",
      "type": "registry:ui",
      "title": "Currency Input",
      "description": "React Native Currency Input for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/number-input.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/number-input.tsx",
          "content": "import { Input, type InputProps } from \"./input\";\n\nexport interface NumberInputProps extends Omit<InputProps, \"keyboardType\" | \"value\" | \"onChangeText\"> {\n  value?: number;\n  onValueChange?: (value: number | undefined) => void;\n  prefix?: string;\n}\n\nexport function NumberInput({\n  value,\n  onValueChange,\n  prefix,\n  ...props\n}: NumberInputProps) {\n  return (\n    <Input\n      keyboardType=\"decimal-pad\"\n      value={\n        value === undefined || Number.isNaN(value)\n          ? \"\"\n          : `${prefix ?? \"\"}${value}`\n      }\n      onChangeText={(t) => {\n        const raw = t.replace(/[^\\d.-]/g, \"\");\n        if (raw === \"\" || raw === \"-\") {\n          onValueChange?.(undefined);\n          return;\n        }\n        onValueChange?.(Number(raw));\n      }}\n      {...props}\n    />\n  );\n}\n\nexport type CurrencyInputProps = NumberInputProps;\n\nexport function CurrencyInput({ prefix = \"$\", ...props }: CurrencyInputProps) {\n  return <NumberInput prefix={prefix} {...props} />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "otp-input",
      "type": "registry:ui",
      "title": "Otp Input",
      "description": "React Native Otp Input for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/otp-input.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/otp-input.tsx",
          "content": "import { useRef } from \"react\";\nimport { TextInput, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Input } from \"./input\";\n\nexport interface OtpInputProps {\n  length?: number;\n  value: string;\n  onChange: (value: string) => void;\n}\n\nexport function OtpInput({ length = 6, value, onChange }: OtpInputProps) {\n  const { theme } = useTheme();\n  const refs = useRef<Array<TextInput | null>>([]);\n  const chars = value.split(\"\");\n\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {Array.from({ length }, (_, i) => (\n        <Input\n          key={i}\n          ref={(el) => {\n            refs.current[i] = el;\n          }}\n          value={chars[i] ?? \"\"}\n          keyboardType=\"number-pad\"\n          maxLength={1}\n          onChangeText={(t) => {\n            const next = chars.slice();\n            next[i] = t.slice(-1);\n            const joined = Array.from({ length }, (__, j) => next[j] ?? \"\").join(\"\");\n            onChange(joined);\n            if (t && i < length - 1) refs.current[i + 1]?.focus();\n          }}\n          style={{ flex: 1, textAlign: \"center\", paddingHorizontal: 0 }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function PinInput(props: OtpInputProps) {\n  return <OtpInput length={props.length ?? 4} {...props} />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "pin-input",
      "type": "registry:ui",
      "title": "Pin Input",
      "description": "React Native Pin Input for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/otp-input.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/otp-input.tsx",
          "content": "import { useRef } from \"react\";\nimport { TextInput, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Input } from \"./input\";\n\nexport interface OtpInputProps {\n  length?: number;\n  value: string;\n  onChange: (value: string) => void;\n}\n\nexport function OtpInput({ length = 6, value, onChange }: OtpInputProps) {\n  const { theme } = useTheme();\n  const refs = useRef<Array<TextInput | null>>([]);\n  const chars = value.split(\"\");\n\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[2] }}>\n      {Array.from({ length }, (_, i) => (\n        <Input\n          key={i}\n          ref={(el) => {\n            refs.current[i] = el;\n          }}\n          value={chars[i] ?? \"\"}\n          keyboardType=\"number-pad\"\n          maxLength={1}\n          onChangeText={(t) => {\n            const next = chars.slice();\n            next[i] = t.slice(-1);\n            const joined = Array.from({ length }, (__, j) => next[j] ?? \"\").join(\"\");\n            onChange(joined);\n            if (t && i < length - 1) refs.current[i + 1]?.focus();\n          }}\n          style={{ flex: 1, textAlign: \"center\", paddingHorizontal: 0 }}\n        />\n      ))}\n    </View>\n  );\n}\n\nexport function PinInput(props: OtpInputProps) {\n  return <OtpInput length={props.length ?? 4} {...props} />;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "pagination",
      "type": "registry:ui",
      "title": "Pagination",
      "description": "React Native Pagination for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/pagination.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/pagination.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  Pressable,\n  Text,\n  View,\n  type PressableProps,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\nimport { pressedOpacity } from \"../utils/pressable\";\n\nexport const Pagination = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        accessibilityRole=\"none\"\n        style={cn(\n          {\n            flexDirection: \"row\",\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            gap: theme.spacing[1],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nPagination.displayName = \"Pagination\";\n\nexport const PaginationContent = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flexDirection: \"row\",\n            alignItems: \"center\",\n            gap: theme.spacing[1],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nPaginationContent.displayName = \"PaginationContent\";\n\nexport const PaginationItem = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => <View ref={ref} style={style} {...props} />,\n);\nPaginationItem.displayName = \"PaginationItem\";\n\nexport interface PaginationLinkProps extends Omit<PressableProps, \"children\"> {\n  isActive?: boolean;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const PaginationLink = forwardRef<\n  React.ElementRef<typeof Pressable>,\n  PaginationLinkProps\n>(({ isActive, children, style, disabled, ...props }, ref) => {\n  const { theme, colors } = useTheme();\n  return (\n    <Pressable\n      ref={ref}\n      accessibilityRole=\"button\"\n      accessibilityState={{ selected: !!isActive, disabled: !!disabled }}\n      disabled={disabled}\n      style={({ pressed }) =>\n        cn(\n          {\n            minWidth: 36,\n            height: 36,\n            paddingHorizontal: theme.spacing[2],\n            borderRadius: theme.radii.lg,\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            backgroundColor: isActive ? colors.primary : colors.glassChromeBgEnv,\n            borderWidth: 1,\n            borderColor: isActive ? \"transparent\" : colors.glassChromeBorder,\n            opacity: pressedOpacity(pressed) * (disabled ? 0.5 : 1),\n          },\n          style,\n        )\n      }\n      {...props}\n    >\n      {typeof children === \"string\" || typeof children === \"number\" ? (\n        <Text\n          style={{\n            color: isActive ? colors.primaryForeground : colors.foreground,\n            fontSize: theme.fontSizes.sm,\n            fontWeight: theme.fontWeights.medium,\n          }}\n        >\n          {children}\n        </Text>\n      ) : (\n        children\n      )}\n    </Pressable>\n  );\n});\nPaginationLink.displayName = \"PaginationLink\";\n\nexport function PaginationPrevious(\n  props: Omit<PaginationLinkProps, \"children\">,\n) {\n  return <PaginationLink {...props}>Prev</PaginationLink>;\n}\n\nexport function PaginationNext(props: Omit<PaginationLinkProps, \"children\">) {\n  return <PaginationLink {...props}>Next</PaginationLink>;\n}\n\nexport function PaginationEllipsis() {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        minWidth: 36,\n        height: 36,\n        alignItems: \"center\",\n        justifyContent: \"center\",\n      }}\n    >\n      <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n        …\n      </Text>\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "password-input",
      "type": "registry:ui",
      "title": "Password Input",
      "description": "React Native Password Input for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/password-input.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/password-input.tsx",
          "content": "import { useState } from \"react\";\nimport { Pressable, Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { Input, type InputProps } from \"./input\";\n\nexport type PasswordInputProps = InputProps;\n\nexport function PasswordInput({ style, ...props }: PasswordInputProps) {\n  const [hidden, setHidden] = useState(true);\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ width: \"100%\", position: \"relative\" }}>\n      <Input\n        secureTextEntry={hidden}\n        autoCapitalize=\"none\"\n        autoCorrect={false}\n        style={[{ paddingRight: 56 }, style]}\n        {...props}\n      />\n      <Pressable\n        onPress={() => setHidden((v) => !v)}\n        accessibilityRole=\"button\"\n        accessibilityLabel={hidden ? \"Show password\" : \"Hide password\"}\n        style={{\n          position: \"absolute\",\n          right: theme.spacing[3],\n          top: 0,\n          bottom: 0,\n          justifyContent: \"center\",\n        }}\n      >\n        <Text\n          style={{\n            color: colors.primary,\n            fontSize: theme.fontSizes.xs,\n            fontWeight: theme.fontWeights.medium,\n          }}\n        >\n          {hidden ? \"Show\" : \"Hide\"}\n        </Text>\n      </Pressable>\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "phone-input",
      "type": "registry:ui",
      "title": "Phone Input",
      "description": "React Native Phone Input for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/phone-input.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/phone-input.tsx",
          "content": "import { Input, type InputProps } from \"./input\";\n\nexport type PhoneInputProps = InputProps;\n\nexport function PhoneInput(props: PhoneInputProps) {\n  return (\n    <Input\n      keyboardType=\"phone-pad\"\n      autoComplete=\"tel\"\n      placeholder={props.placeholder ?? \"+1 555 0100\"}\n      {...props}\n    />\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "popover",
      "type": "registry:ui",
      "title": "Popover",
      "description": "React Native Popover for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/popover.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/popover.tsx",
          "content": "import {\n  createContext,\n  forwardRef,\n  useContext,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  Animated,\n  Modal,\n  Pressable,\n  Text,\n  View,\n  type StyleProp,\n  type TextProps,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport {\n  dialogContentStyle,\n  overlayStyle,\n  timings,\n  usePresence,\n} from \"../utils/animation\";\nimport { cn } from \"../utils/cn\";\n\ninterface PopoverContextValue {\n  open: boolean;\n  setOpen: (open: boolean) => void;\n}\n\nconst PopoverContext = createContext<PopoverContextValue | null>(null);\n\nfunction usePopover() {\n  const ctx = useContext(PopoverContext);\n  if (!ctx) throw new Error(\"Popover components must be used within Popover\");\n  return ctx;\n}\n\nexport interface PopoverProps {\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  children?: ReactNode;\n}\n\nexport function Popover({\n  open: openProp,\n  defaultOpen = false,\n  onOpenChange,\n  children,\n}: PopoverProps) {\n  const isControlled = openProp !== undefined;\n  const [internal, setInternal] = useState(defaultOpen);\n  const open = isControlled ? !!openProp : internal;\n  const setOpen = (next: boolean) => {\n    if (!isControlled) setInternal(next);\n    onOpenChange?.(next);\n  };\n  return (\n    <PopoverContext.Provider value={{ open, setOpen }}>\n      {children}\n    </PopoverContext.Provider>\n  );\n}\n\nexport function PopoverTrigger({ children }: { children?: ReactNode }) {\n  const { setOpen, open } = usePopover();\n  return (\n    <Pressable\n      onPress={() => setOpen(!open)}\n      accessibilityRole=\"button\"\n    >\n      {children}\n    </Pressable>\n  );\n}\n\nexport function PopoverAnchor({ children }: { children?: ReactNode }) {\n  return <>{children}</>;\n}\n\nexport interface PopoverContentProps extends ViewProps {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport function PopoverContent({\n  children,\n  style,\n  ...props\n}: PopoverContentProps) {\n  const { theme, colors } = useTheme();\n  const { open, setOpen } = usePopover();\n  const { mounted, progress } = usePresence(open, timings.fast);\n\n  if (!mounted) return null;\n\n  return (\n    <Modal\n      visible={mounted}\n      transparent\n      animationType=\"none\"\n      onRequestClose={() => setOpen(false)}\n    >\n      <View style={{ flex: 1 }}>\n        <Animated.View\n          pointerEvents=\"none\"\n          style={[\n            {\n              position: \"absolute\",\n              left: 0,\n              right: 0,\n              top: 0,\n              bottom: 0,\n              backgroundColor: \"rgba(0,0,0,0.08)\",\n            },\n            overlayStyle(progress),\n          ]}\n        />\n        <Pressable\n          style={{\n            flex: 1,\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            padding: theme.spacing[6],\n          }}\n          onPress={() => setOpen(false)}\n        >\n          <Animated.View style={dialogContentStyle(progress)}>\n            <Pressable\n              onPress={(e) => e.stopPropagation?.()}\n              style={cn(\n                {\n                  minWidth: 220,\n                  maxWidth: 320,\n                  borderRadius: theme.radii.xl,\n                  backgroundColor: colors.popover,\n                  borderWidth: 1,\n                  borderColor: colors.glassChromeBorder,\n                  padding: theme.spacing[4],\n                },\n                style,\n              )}\n              {...props}\n            >\n              {children}\n            </Pressable>\n          </Animated.View>\n        </Pressable>\n      </View>\n    </Modal>\n  );\n}\n\nexport const PopoverHeader = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn({ marginBottom: theme.spacing[2], gap: 4 }, style)}\n        {...props}\n      />\n    );\n  },\n);\nPopoverHeader.displayName = \"PopoverHeader\";\n\nexport const PopoverTitle = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color: colors.foreground,\n            fontSize: theme.fontSizes.sm,\n            fontWeight: theme.fontWeights.semibold,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nPopoverTitle.displayName = \"PopoverTitle\";\n\nexport const PopoverDescription = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color: colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nPopoverDescription.displayName = \"PopoverDescription\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "progress",
      "type": "registry:ui",
      "title": "Progress",
      "description": "React Native Progress for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/progress.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/progress.tsx",
          "content": "import { forwardRef } from \"react\";\nimport {\n  Animated,\n  View,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { useProgressWidth } from \"../utils/animation\";\nimport { cn } from \"../utils/cn\";\n\nexport type ProgressVariant = \"chrome\" | \"outline\";\nexport type ProgressSize = \"sm\" | \"default\" | \"lg\";\n\nexport interface ProgressProps extends ViewProps {\n  value?: number;\n  max?: number;\n  variant?: ProgressVariant;\n  size?: ProgressSize;\n  style?: StyleProp<ViewStyle>;\n  indicatorStyle?: StyleProp<ViewStyle>;\n}\n\nexport const Progress = forwardRef<View, ProgressProps>(\n  (\n    {\n      value = 0,\n      max = 100,\n      variant = \"chrome\",\n      size = \"default\",\n      style,\n      indicatorStyle,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const height = size === \"sm\" ? 6 : size === \"lg\" ? 12 : 8;\n    const pct = Math.min(100, Math.max(0, (value / max) * 100));\n    const width = useProgressWidth(pct);\n\n    return (\n      <View\n        ref={ref}\n        accessibilityRole=\"progressbar\"\n        accessibilityValue={{ min: 0, max, now: value }}\n        style={cn(\n          {\n            width: \"100%\",\n            height,\n            borderRadius: theme.radii.full,\n            overflow: \"hidden\",\n            borderWidth: 1,\n            borderColor: colors.glassChromeBorder,\n            backgroundColor:\n              variant === \"outline\"\n                ? colors.glassSurfaceFill\n                : colors.glassChromeBgEnv,\n          },\n          style,\n        )}\n        {...props}\n      >\n        <Animated.View\n          style={[\n            {\n              height: \"100%\",\n              borderRadius: theme.radii.full,\n              backgroundColor: colors.primary,\n              opacity: variant === \"chrome\" ? 0.85 : 1,\n              width: width.interpolate({\n                inputRange: [0, 100],\n                outputRange: [\"0%\", \"100%\"],\n              }),\n            },\n            indicatorStyle,\n          ]}\n        />\n      </View>\n    );\n  },\n);\nProgress.displayName = \"Progress\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "radio-group",
      "type": "registry:ui",
      "title": "Radio Group",
      "description": "React Native Radio Group for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/radio-group.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/radio-group.tsx",
          "content": "import {\n  createContext,\n  forwardRef,\n  useContext,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  Pressable,\n  View,\n  type PressableProps,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\ninterface RadioGroupContextValue {\n  value?: string;\n  onValueChange?: (value: string) => void;\n  disabled?: boolean;\n  size: \"sm\" | \"default\" | \"lg\";\n  variant: \"chrome\" | \"outline\";\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextValue>({\n  size: \"default\",\n  variant: \"chrome\",\n});\n\nexport interface RadioGroupProps extends ViewProps {\n  value?: string;\n  defaultValue?: string;\n  onValueChange?: (value: string) => void;\n  disabled?: boolean;\n  size?: \"sm\" | \"default\" | \"lg\";\n  variant?: \"chrome\" | \"outline\";\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const RadioGroup = forwardRef<View, RadioGroupProps>(\n  (\n    {\n      value: valueProp,\n      defaultValue,\n      onValueChange,\n      disabled,\n      size = \"default\",\n      variant = \"chrome\",\n      children,\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme } = useTheme();\n    const isControlled = valueProp !== undefined;\n    const [internal, setInternal] = useState(defaultValue);\n    const value = isControlled ? valueProp : internal;\n\n    return (\n      <RadioGroupContext.Provider\n        value={{\n          value,\n          onValueChange: (v) => {\n            if (!isControlled) setInternal(v);\n            onValueChange?.(v);\n          },\n          disabled,\n          size,\n          variant,\n        }}\n      >\n        <View\n          ref={ref}\n          accessibilityRole=\"radiogroup\"\n          style={cn({ gap: theme.spacing[2] }, style)}\n          {...props}\n        >\n          {children}\n        </View>\n      </RadioGroupContext.Provider>\n    );\n  },\n);\nRadioGroup.displayName = \"RadioGroup\";\n\nexport interface RadioGroupItemProps extends Omit<PressableProps, \"onPress\"> {\n  value: string;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const RadioGroupItem = forwardRef<\n  React.ElementRef<typeof Pressable>,\n  RadioGroupItemProps\n>(({ value, disabled, style, ...props }, ref) => {\n  const { theme, colors } = useTheme();\n  const ctx = useContext(RadioGroupContext);\n  const selected = ctx.value === value;\n  const isDisabled = disabled || ctx.disabled;\n  const dim = ctx.size === \"sm\" ? 16 : ctx.size === \"lg\" ? 22 : 18;\n  const dot = dim * 0.45;\n\n  return (\n    <Pressable\n      ref={ref}\n      accessibilityRole=\"radio\"\n      accessibilityState={{ selected, disabled: !!isDisabled }}\n      disabled={isDisabled}\n      onPress={() => ctx.onValueChange?.(value)}\n      style={cn(\n        {\n          width: dim,\n          height: dim,\n          borderRadius: theme.radii.full,\n          borderWidth: 1.5,\n          borderColor: selected ? colors.primary : colors.glassChromeBorder,\n          backgroundColor:\n            ctx.variant === \"outline\"\n              ? colors.glassSurfaceFill\n              : colors.glassChromeBgEnv,\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          opacity: isDisabled ? 0.5 : 1,\n        },\n        style,\n      )}\n      {...props}\n    >\n      {selected ? (\n        <View\n          style={{\n            width: dot,\n            height: dot,\n            borderRadius: theme.radii.full,\n            backgroundColor: colors.primary,\n          }}\n        />\n      ) : null}\n    </Pressable>\n  );\n});\nRadioGroupItem.displayName = \"RadioGroupItem\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "rating",
      "type": "registry:ui",
      "title": "Rating",
      "description": "React Native Rating for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/rating.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/rating.tsx",
          "content": "import { Pressable, Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport function Rating({\n  value,\n  onChange,\n  max = 5,\n}: {\n  value: number;\n  onChange?: (value: number) => void;\n  max?: number;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", gap: theme.spacing[1] }}>\n      {Array.from({ length: max }, (_, i) => {\n        const n = i + 1;\n        const on = n <= value;\n        return (\n          <Pressable key={n} onPress={() => onChange?.(n)}>\n            <Text style={{ fontSize: 22, color: on ? colors.primary : colors.mutedForeground }}>\n              ★\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "scroll-area",
      "type": "registry:ui",
      "title": "Scroll Area",
      "description": "React Native Scroll Area for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/scroll-area.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/scroll-area.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  ScrollView,\n  type ScrollViewProps,\n  type StyleProp,\n  type ViewStyle,\n} from \"react-native\";\nimport { cn } from \"../utils/cn\";\n\nexport interface ScrollAreaProps extends ScrollViewProps {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n  contentContainerStyle?: StyleProp<ViewStyle>;\n  horizontal?: boolean;\n}\n\nexport const ScrollArea = forwardRef<ScrollView, ScrollAreaProps>(\n  ({ children, style, contentContainerStyle, horizontal, ...props }, ref) => {\n    return (\n      <ScrollView\n        ref={ref}\n        horizontal={horizontal}\n        showsVerticalScrollIndicator={!horizontal}\n        showsHorizontalScrollIndicator={!!horizontal}\n        style={cn({ flexGrow: 0 }, style)}\n        contentContainerStyle={contentContainerStyle}\n        {...props}\n      >\n        {children}\n      </ScrollView>\n    );\n  },\n);\nScrollArea.displayName = \"ScrollArea\";\n\n/** Visual stub for web ScrollBar parity — RN uses native indicators. */\nexport function ScrollBar() {\n  return null;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "scroll-to-top",
      "type": "registry:ui",
      "title": "Scroll To Top",
      "description": "React Native Scroll To Top for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/scroll-to-top.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/scroll-to-top.tsx",
          "content": "import { forwardRef } from \"react\";\nimport {\n  Pressable,\n  Text,\n  type NativeScrollEvent,\n  type NativeSyntheticEvent,\n  type PressableProps,\n  type StyleProp,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\nimport { pressedOpacity } from \"../utils/pressable\";\n\nexport interface ScrollToTopProps extends Omit<PressableProps, \"onPress\"> {\n  /** Current scroll offset Y (pass from ScrollView onScroll). */\n  offsetY?: number;\n  /** Show button after this offset. Default 320. */\n  threshold?: number;\n  onPress?: () => void;\n  label?: string;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const ScrollToTop = forwardRef<\n  React.ElementRef<typeof Pressable>,\n  ScrollToTopProps\n>(\n  (\n    {\n      offsetY = 0,\n      threshold = 320,\n      onPress,\n      label = \"↑\",\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    if (offsetY < threshold) return null;\n\n    return (\n      <Pressable\n        ref={ref}\n        accessibilityRole=\"button\"\n        accessibilityLabel=\"Scroll to top\"\n        onPress={onPress}\n        style={({ pressed }) =>\n          cn(\n            {\n              position: \"absolute\",\n              right: theme.spacing[4],\n              bottom: theme.spacing[6],\n              width: 44,\n              height: 44,\n              borderRadius: theme.radii.full,\n              backgroundColor: colors.glassChromeBgEnv,\n              borderWidth: 1,\n              borderColor: colors.glassChromeBorder,\n              alignItems: \"center\",\n              justifyContent: \"center\",\n              opacity: pressedOpacity(pressed),\n              zIndex: theme.zIndex.sticky,\n            },\n            style,\n          )\n        }\n        {...props}\n      >\n        <Text\n          style={{\n            color: colors.glassChromeFg,\n            fontSize: theme.fontSizes.lg,\n            fontWeight: theme.fontWeights.bold,\n          }}\n        >\n          {label}\n        </Text>\n      </Pressable>\n    );\n  },\n);\nScrollToTop.displayName = \"ScrollToTop\";\n\n/** Helper to extract offset from ScrollView onScroll events. */\nexport function getScrollOffsetY(\n  e: NativeSyntheticEvent<NativeScrollEvent>,\n): number {\n  return e.nativeEvent.contentOffset.y;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "search-input",
      "type": "registry:ui",
      "title": "Search Input",
      "description": "React Native Search Input for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/search-input.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/search-input.tsx",
          "content": "import { Input, type InputProps } from \"./input\";\n\nexport type SearchInputProps = InputProps;\n\nexport function SearchInput(props: SearchInputProps) {\n  return (\n    <Input\n      autoCapitalize=\"none\"\n      autoCorrect={false}\n      returnKeyType=\"search\"\n      placeholder={props.placeholder ?? \"Search\"}\n      {...props}\n    />\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "select",
      "type": "registry:ui",
      "title": "Select",
      "description": "React Native Select for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/select.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/select.tsx",
          "content": "import {\n  createContext,\n  forwardRef,\n  useContext,\n  useMemo,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  Animated,\n  FlatList,\n  Modal,\n  Pressable,\n  Text,\n  View,\n  type PressableProps,\n  type StyleProp,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport {\n  overlayStyle,\n  sheetContentStyle,\n  timings,\n  usePresence,\n} from \"../utils/animation\";\nimport { cn } from \"../utils/cn\";\nimport { pressedOpacity } from \"../utils/pressable\";\n\ninterface SelectContextValue {\n  open: boolean;\n  setOpen: (open: boolean) => void;\n  value?: string;\n  onValueChange?: (value: string) => void;\n  labelByValue: Map<string, string>;\n  registerLabel: (value: string, label: string) => void;\n  size: \"sm\" | \"default\" | \"lg\";\n  variant: \"chrome\" | \"outline\";\n  disabled?: boolean;\n}\n\nconst SelectContext = createContext<SelectContextValue | null>(null);\n\nfunction useSelect() {\n  const ctx = useContext(SelectContext);\n  if (!ctx) throw new Error(\"Select components must be used within Select\");\n  return ctx;\n}\n\nexport interface SelectProps {\n  value?: string;\n  defaultValue?: string;\n  onValueChange?: (value: string) => void;\n  open?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  disabled?: boolean;\n  size?: \"sm\" | \"default\" | \"lg\";\n  variant?: \"chrome\" | \"outline\";\n  children?: ReactNode;\n}\n\nexport function Select({\n  value: valueProp,\n  defaultValue,\n  onValueChange,\n  open: openProp,\n  onOpenChange,\n  disabled,\n  size = \"default\",\n  variant = \"chrome\",\n  children,\n}: SelectProps) {\n  const isValueControlled = valueProp !== undefined;\n  const isOpenControlled = openProp !== undefined;\n  const [internalValue, setInternalValue] = useState(defaultValue);\n  const [internalOpen, setInternalOpen] = useState(false);\n  const [labels, setLabels] = useState<Map<string, string>>(new Map());\n\n  const value = isValueControlled ? valueProp : internalValue;\n  const open = isOpenControlled ? !!openProp : internalOpen;\n\n  const setOpen = (next: boolean) => {\n    if (!isOpenControlled) setInternalOpen(next);\n    onOpenChange?.(next);\n  };\n\n  const registerLabel = (v: string, label: string) => {\n    setLabels((prev) => {\n      if (prev.get(v) === label) return prev;\n      const next = new Map(prev);\n      next.set(v, label);\n      return next;\n    });\n  };\n\n  const ctx = useMemo(\n    () => ({\n      open,\n      setOpen,\n      value,\n      onValueChange: (v: string) => {\n        if (!isValueControlled) setInternalValue(v);\n        onValueChange?.(v);\n        setOpen(false);\n      },\n      labelByValue: labels,\n      registerLabel,\n      size,\n      variant,\n      disabled,\n    }),\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    [open, value, labels, size, variant, disabled],\n  );\n\n  return (\n    <SelectContext.Provider value={ctx}>{children}</SelectContext.Provider>\n  );\n}\n\nexport interface SelectTriggerProps extends Omit<PressableProps, \"children\"> {\n  placeholder?: string;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const SelectTrigger = forwardRef<\n  React.ElementRef<typeof Pressable>,\n  SelectTriggerProps\n>(({ placeholder = \"Select…\", children, style, ...props }, ref) => {\n  const { theme, colors } = useTheme();\n  const ctx = useSelect();\n  const height = ctx.size === \"sm\" ? 36 : ctx.size === \"lg\" ? 44 : 40;\n  const label =\n    (ctx.value && ctx.labelByValue.get(ctx.value)) || children || placeholder;\n\n  return (\n    <Pressable\n      ref={ref}\n      accessibilityRole=\"button\"\n      disabled={ctx.disabled}\n      onPress={() => ctx.setOpen(true)}\n      style={({ pressed }) =>\n        cn(\n          {\n            height,\n            width: \"100%\",\n            flexDirection: \"row\",\n            alignItems: \"center\",\n            justifyContent: \"space-between\",\n            paddingHorizontal: theme.spacing[3],\n            borderRadius: theme.radii.xl,\n            borderWidth: 1,\n            borderColor: colors.glassChromeBorder,\n            backgroundColor:\n              ctx.variant === \"outline\"\n                ? colors.glassSurfaceFill\n                : colors.glassChromeBgEnv,\n            opacity: pressedOpacity(pressed) * (ctx.disabled ? 0.5 : 1),\n          },\n          style,\n        )\n      }\n      {...props}\n    >\n      {typeof label === \"string\" || typeof label === \"number\" ? (\n        <Text\n          style={{\n            color: ctx.value ? colors.glassChromeFg : colors.glassChromeFgMuted,\n            fontSize: theme.fontSizes.sm,\n            flex: 1,\n          }}\n          numberOfLines={1}\n        >\n          {label}\n        </Text>\n      ) : (\n        label\n      )}\n      <Text style={{ color: colors.glassChromeFgMuted, marginLeft: 8 }}>▾</Text>\n    </Pressable>\n  );\n});\nSelectTrigger.displayName = \"SelectTrigger\";\n\nexport function SelectValue({ placeholder }: { placeholder?: string }) {\n  const { colors, theme } = useTheme();\n  const ctx = useSelect();\n  const label = ctx.value\n    ? ctx.labelByValue.get(ctx.value) ?? ctx.value\n    : placeholder ?? \"Select…\";\n  return (\n    <Text\n      style={{\n        color: ctx.value ? colors.glassChromeFg : colors.glassChromeFgMuted,\n        fontSize: theme.fontSizes.sm,\n      }}\n      numberOfLines={1}\n    >\n      {label}\n    </Text>\n  );\n}\n\nexport interface SelectContentProps {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n  title?: string;\n}\n\n/** Collects SelectItem children for the modal list. */\nexport function SelectContent({ children, style, title }: SelectContentProps) {\n  const { theme, colors } = useTheme();\n  const ctx = useSelect();\n  const items = flattenSelectItems(children);\n  const { mounted, progress } = usePresence(ctx.open, timings.normal);\n\n  if (!mounted) {\n    // Keep children mounted for label registration even when closed\n    return (\n      <View style={{ height: 0, overflow: \"hidden\" }}>{children}</View>\n    );\n  }\n\n  return (\n    <>\n      <View style={{ height: 0, overflow: \"hidden\" }}>{children}</View>\n      <Modal\n        visible={mounted}\n        transparent\n        animationType=\"none\"\n        onRequestClose={() => ctx.setOpen(false)}\n      >\n        <View style={{ flex: 1, justifyContent: \"flex-end\" }}>\n          <Pressable\n            style={{ flex: 1 }}\n            onPress={() => ctx.setOpen(false)}\n          >\n            <Animated.View\n              style={[\n                { flex: 1, backgroundColor: colors.overlay },\n                overlayStyle(progress),\n              ]}\n            />\n          </Pressable>\n          <Animated.View\n            style={[\n              sheetContentStyle(progress, \"bottom\"),\n              {\n                backgroundColor: colors.popover,\n                borderTopLeftRadius: theme.radii[\"2xl\"],\n                borderTopRightRadius: theme.radii[\"2xl\"],\n                borderWidth: 1,\n                borderColor: colors.glassChromeBorder,\n                maxHeight: \"55%\",\n                paddingBottom: theme.spacing[8],\n              },\n              style,\n            ]}\n          >\n            <View\n              style={{\n                alignItems: \"center\",\n                paddingVertical: theme.spacing[3],\n              }}\n            >\n              <View\n                style={{\n                  width: 36,\n                  height: 4,\n                  borderRadius: 2,\n                  backgroundColor: colors.border,\n                }}\n              />\n              {title ? (\n                <Text\n                  style={{\n                    marginTop: theme.spacing[2],\n                    color: colors.foreground,\n                    fontWeight: theme.fontWeights.semibold,\n                  }}\n                >\n                  {title}\n                </Text>\n              ) : null}\n            </View>\n            <FlatList\n              data={items}\n              keyExtractor={(item) => item.value}\n              renderItem={({ item }) => (\n                <SelectItemRow value={item.value} label={item.label} />\n              )}\n            />\n          </Animated.View>\n        </View>\n      </Modal>\n    </>\n  );\n}\n\nfunction SelectItemRow({ value, label }: { value: string; label: string }) {\n  const { theme, colors } = useTheme();\n  const ctx = useSelect();\n  const selected = ctx.value === value;\n\n  return (\n    <Pressable\n      accessibilityRole=\"button\"\n      accessibilityState={{ selected }}\n      onPress={() => ctx.onValueChange?.(value)}\n      style={({ pressed }) => ({\n        paddingHorizontal: theme.spacing[4],\n        paddingVertical: theme.spacing[3.5],\n        backgroundColor: selected\n          ? colors.glassChromeBgEnv\n          : pressed\n            ? colors.muted\n            : \"transparent\",\n        flexDirection: \"row\",\n        alignItems: \"center\",\n        justifyContent: \"space-between\",\n      })}\n    >\n      <Text\n        style={{\n          color: colors.foreground,\n          fontSize: theme.fontSizes.base,\n          fontWeight: selected\n            ? theme.fontWeights.semibold\n            : theme.fontWeights.normal,\n        }}\n      >\n        {label}\n      </Text>\n      {selected ? (\n        <Text style={{ color: colors.primary, fontWeight: \"700\" }}>✓</Text>\n      ) : null}\n    </Pressable>\n  );\n}\n\nexport interface SelectItemProps {\n  value: string;\n  children?: ReactNode;\n  disabled?: boolean;\n}\n\n/** Registers option label; rendered invisibly inside SelectContent. */\nexport function SelectItem({ value, children }: SelectItemProps) {\n  const ctx = useSelect();\n  const label =\n    typeof children === \"string\" || typeof children === \"number\"\n      ? String(children)\n      : value;\n\n  // register on each render (map is stable if unchanged)\n  ctx.registerLabel(value, label);\n  return null;\n}\n\nexport function SelectGroup({ children }: { children?: ReactNode }) {\n  return <>{children}</>;\n}\n\nexport function SelectLabel({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <Text\n      style={{\n        paddingHorizontal: theme.spacing[4],\n        paddingVertical: theme.spacing[2],\n        color: colors.mutedForeground,\n        fontSize: theme.fontSizes.xs,\n        fontWeight: theme.fontWeights.semibold,\n        textTransform: \"uppercase\",\n      }}\n    >\n      {children}\n    </Text>\n  );\n}\n\nexport function SelectSeparator() {\n  const { colors } = useTheme();\n  return (\n    <View\n      style={{\n        height: 1,\n        backgroundColor: colors.border,\n        marginVertical: 4,\n      }}\n    />\n  );\n}\n\nfunction flattenSelectItems(\n  children: ReactNode,\n): Array<{ value: string; label: string }> {\n  const items: Array<{ value: string; label: string }> = [];\n\n  function walk(node: ReactNode) {\n    if (node == null || typeof node === \"boolean\") return;\n    if (Array.isArray(node)) {\n      node.forEach(walk);\n      return;\n    }\n    if (typeof node === \"object\" && node !== null && \"props\" in node) {\n      const el = node as {\n        type?: { displayName?: string; name?: string };\n        props?: { value?: string; children?: ReactNode };\n      };\n      const name = el.type?.displayName || el.type?.name;\n      if (name === \"SelectItem\" && el.props?.value) {\n        const label =\n          typeof el.props.children === \"string\" ||\n          typeof el.props.children === \"number\"\n            ? String(el.props.children)\n            : el.props.value;\n        items.push({ value: el.props.value, label });\n      } else if (el.props?.children) {\n        walk(el.props.children);\n      }\n    }\n  }\n\n  walk(children);\n  return items;\n}\n\nSelectItem.displayName = \"SelectItem\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "separator",
      "type": "registry:ui",
      "title": "Separator",
      "description": "React Native Separator for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/separator.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/separator.tsx",
          "content": "import { forwardRef } from \"react\";\nimport { View, type StyleProp, type ViewProps, type ViewStyle } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type SeparatorVariant = \"default\" | \"chrome\" | \"subtle\";\n\nexport interface SeparatorProps extends ViewProps {\n  orientation?: \"horizontal\" | \"vertical\";\n  variant?: SeparatorVariant;\n  decorative?: boolean;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Separator = forwardRef<View, SeparatorProps>(\n  (\n    {\n      orientation = \"horizontal\",\n      variant = \"default\",\n      decorative = true,\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const { colors } = useTheme();\n    const bg =\n      variant === \"subtle\"\n        ? \"rgba(128,128,128,0.25)\"\n        : variant === \"chrome\"\n          ? colors.glassChromeBorder\n          : colors.glassChromeBorder;\n\n    return (\n      <View\n        ref={ref}\n        accessibilityRole={decorative ? undefined : \"none\"}\n        importantForAccessibility={decorative ? \"no\" : \"yes\"}\n        style={cn(\n          orientation === \"horizontal\"\n            ? { height: 1, width: \"100%\", backgroundColor: bg }\n            : { width: 1, height: \"100%\", backgroundColor: bg, alignSelf: \"stretch\" },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nSeparator.displayName = \"Separator\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "sheet",
      "type": "registry:ui",
      "title": "Sheet",
      "description": "React Native Sheet for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/sheet.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/sheet.tsx",
          "content": "import {\n  createContext,\n  forwardRef,\n  useContext,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  Animated,\n  Modal,\n  Pressable,\n  Text,\n  View,\n  type StyleProp,\n  type TextProps,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport {\n  overlayStyle,\n  sheetContentStyle,\n  timings,\n  usePresence,\n} from \"../utils/animation\";\nimport { cn } from \"../utils/cn\";\n\ninterface SheetContextValue {\n  open: boolean;\n  setOpen: (open: boolean) => void;\n}\n\nconst SheetContext = createContext<SheetContextValue | null>(null);\n\nfunction useSheet() {\n  const ctx = useContext(SheetContext);\n  if (!ctx) throw new Error(\"Sheet components must be used within Sheet\");\n  return ctx;\n}\n\nexport interface SheetProps {\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  children?: ReactNode;\n}\n\nexport function Sheet({\n  open: openProp,\n  defaultOpen = false,\n  onOpenChange,\n  children,\n}: SheetProps) {\n  const isControlled = openProp !== undefined;\n  const [internal, setInternal] = useState(defaultOpen);\n  const open = isControlled ? !!openProp : internal;\n  const setOpen = (next: boolean) => {\n    if (!isControlled) setInternal(next);\n    onOpenChange?.(next);\n  };\n  return (\n    <SheetContext.Provider value={{ open, setOpen }}>\n      {children}\n    </SheetContext.Provider>\n  );\n}\n\nexport function SheetTrigger({ children }: { children?: ReactNode }) {\n  const { setOpen } = useSheet();\n  return (\n    <Pressable onPress={() => setOpen(true)} accessibilityRole=\"button\">\n      {children}\n    </Pressable>\n  );\n}\n\nexport function SheetClose({ children }: { children?: ReactNode }) {\n  const { setOpen } = useSheet();\n  return (\n    <Pressable onPress={() => setOpen(false)} accessibilityRole=\"button\">\n      {children}\n    </Pressable>\n  );\n}\n\nexport type SheetSide = \"bottom\" | \"top\" | \"left\" | \"right\";\n\nexport interface SheetContentProps extends ViewProps {\n  side?: SheetSide;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n  showClose?: boolean;\n}\n\nexport function SheetContent({\n  side = \"bottom\",\n  children,\n  style,\n  showClose = true,\n  ...props\n}: SheetContentProps) {\n  const { theme, colors } = useTheme();\n  const { open, setOpen } = useSheet();\n  const { mounted, progress } = usePresence(open, timings.slow);\n\n  const sideStyle: ViewStyle =\n    side === \"bottom\"\n      ? {\n          position: \"absolute\",\n          left: 0,\n          right: 0,\n          bottom: 0,\n          borderTopLeftRadius: theme.radii[\"2xl\"],\n          borderTopRightRadius: theme.radii[\"2xl\"],\n          maxHeight: \"85%\",\n          paddingBottom: theme.spacing[8],\n        }\n      : side === \"top\"\n        ? {\n            position: \"absolute\",\n            left: 0,\n            right: 0,\n            top: 0,\n            borderBottomLeftRadius: theme.radii[\"2xl\"],\n            borderBottomRightRadius: theme.radii[\"2xl\"],\n            maxHeight: \"85%\",\n          }\n        : side === \"left\"\n          ? {\n              position: \"absolute\",\n              left: 0,\n              top: 0,\n              bottom: 0,\n              width: \"80%\",\n              maxWidth: 360,\n              borderTopRightRadius: theme.radii[\"2xl\"],\n              borderBottomRightRadius: theme.radii[\"2xl\"],\n            }\n          : {\n              position: \"absolute\",\n              right: 0,\n              top: 0,\n              bottom: 0,\n              width: \"80%\",\n              maxWidth: 360,\n              borderTopLeftRadius: theme.radii[\"2xl\"],\n              borderBottomLeftRadius: theme.radii[\"2xl\"],\n            };\n\n  if (!mounted) return null;\n\n  return (\n    <Modal\n      visible={mounted}\n      transparent\n      animationType=\"none\"\n      onRequestClose={() => setOpen(false)}\n    >\n      <View style={{ flex: 1 }}>\n        <Pressable\n          style={{ flex: 1 }}\n          onPress={() => setOpen(false)}\n        >\n          <Animated.View\n            style={[\n              {\n                flex: 1,\n                backgroundColor: colors.overlay,\n              },\n              overlayStyle(progress),\n            ]}\n          />\n        </Pressable>\n        <Animated.View\n          style={[\n            sheetContentStyle(progress, side),\n            sideStyle,\n            {\n              backgroundColor: colors.popover,\n              borderWidth: 1,\n              borderColor: colors.glassChromeBorder,\n              padding: theme.spacing[6],\n            },\n            style,\n          ]}\n          {...props}\n        >\n          <Pressable onPress={(e) => e.stopPropagation?.()}>\n            {side === \"bottom\" ? (\n              <View\n                style={{\n                  alignItems: \"center\",\n                  marginBottom: theme.spacing[3],\n                }}\n              >\n                <View\n                  style={{\n                    width: 36,\n                    height: 4,\n                    borderRadius: 2,\n                    backgroundColor: colors.border,\n                  }}\n                />\n              </View>\n            ) : null}\n            {showClose ? (\n              <Pressable\n                onPress={() => setOpen(false)}\n                accessibilityLabel=\"Close\"\n                style={{\n                  position: \"absolute\",\n                  top: theme.spacing[3],\n                  right: theme.spacing[3],\n                  zIndex: 1,\n                  padding: theme.spacing[2],\n                }}\n              >\n                <Text style={{ color: colors.mutedForeground, fontSize: 18 }}>✕</Text>\n              </Pressable>\n            ) : null}\n            {children}\n          </Pressable>\n        </Animated.View>\n      </View>\n    </Modal>\n  );\n}\n\nexport const SheetHeader = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flexDirection: \"column\",\n            gap: theme.spacing[1.5],\n            marginBottom: theme.spacing[4],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nSheetHeader.displayName = \"SheetHeader\";\n\nexport const SheetFooter = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flexDirection: \"row\",\n            gap: theme.spacing[2],\n            marginTop: theme.spacing[4],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nSheetFooter.displayName = \"SheetFooter\";\n\nexport const SheetTitle = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color: colors.foreground,\n            fontSize: theme.fontSizes.lg,\n            fontWeight: theme.fontWeights.semibold,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nSheetTitle.displayName = \"SheetTitle\";\n\nexport const SheetDescription = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color: colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nSheetDescription.displayName = \"SheetDescription\";\n\nexport const SheetPortal = ({ children }: { children?: ReactNode }) => (\n  <>{children}</>\n);\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "sidebar",
      "type": "registry:ui",
      "title": "Sidebar",
      "description": "React Native Sidebar for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "separator"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/sidebar.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/sidebar.tsx",
          "content": "import {\n  createContext,\n  forwardRef,\n  useContext,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  Modal,\n  Pressable,\n  Text,\n  View,\n  type PressableProps,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\nimport { Separator } from \"./separator\";\n\ninterface SidebarContextValue {\n  open: boolean;\n  setOpen: (open: boolean) => void;\n  toggle: () => void;\n}\n\nconst SidebarContext = createContext<SidebarContextValue | null>(null);\n\nexport function useSidebar() {\n  const ctx = useContext(SidebarContext);\n  if (!ctx) throw new Error(\"useSidebar must be used within SidebarProvider\");\n  return ctx;\n}\n\nexport interface SidebarProviderProps {\n  defaultOpen?: boolean;\n  open?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport function SidebarProvider({\n  defaultOpen = false,\n  open: openProp,\n  onOpenChange,\n  children,\n  style,\n}: SidebarProviderProps) {\n  const isControlled = openProp !== undefined;\n  const [internal, setInternal] = useState(defaultOpen);\n  const open = isControlled ? !!openProp : internal;\n  const setOpen = (next: boolean) => {\n    if (!isControlled) setInternal(next);\n    onOpenChange?.(next);\n  };\n\n  return (\n    <SidebarContext.Provider\n      value={{ open, setOpen, toggle: () => setOpen(!open) }}\n    >\n      <View style={cn({ flex: 1, flexDirection: \"row\" }, style)}>\n        {children}\n      </View>\n    </SidebarContext.Provider>\n  );\n}\n\nexport interface SidebarProps extends ViewProps {\n  side?: \"left\" | \"right\";\n  /** Use modal drawer overlay (mobile default). */\n  collapsible?: \"offcanvas\" | \"none\";\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n  width?: number;\n}\n\nexport function Sidebar({\n  side = \"left\",\n  collapsible = \"offcanvas\",\n  children,\n  style,\n  width = 280,\n  ...props\n}: SidebarProps) {\n  const { theme, colors } = useTheme();\n  const { open, setOpen } = useSidebar();\n\n  if (collapsible === \"none\") {\n    return (\n      <View\n        style={cn(\n          {\n            width,\n            backgroundColor: colors.glassChromeBgEnv,\n            borderRightWidth: side === \"left\" ? 1 : 0,\n            borderLeftWidth: side === \"right\" ? 1 : 0,\n            borderColor: colors.glassChromeBorder,\n            padding: theme.spacing[3],\n          },\n          style,\n        )}\n        {...props}\n      >\n        {children}\n      </View>\n    );\n  }\n\n  return (\n    <Modal\n      visible={open}\n      transparent\n      animationType=\"fade\"\n      onRequestClose={() => setOpen(false)}\n    >\n      <Pressable\n        style={{ flex: 1, backgroundColor: colors.overlay, flexDirection: \"row\" }}\n        onPress={() => setOpen(false)}\n      >\n        <Pressable\n          onPress={(e) => e.stopPropagation?.()}\n          style={cn(\n            {\n              width,\n              height: \"100%\",\n              backgroundColor: colors.popover,\n              borderColor: colors.glassChromeBorder,\n              borderRightWidth: side === \"left\" ? 1 : 0,\n              borderLeftWidth: side === \"right\" ? 1 : 0,\n              padding: theme.spacing[3],\n              marginLeft: side === \"right\" ? \"auto\" : 0,\n            },\n            style,\n          )}\n          {...props}\n        >\n          {children}\n        </Pressable>\n      </Pressable>\n    </Modal>\n  );\n}\n\nexport function SidebarTrigger({\n  style,\n  ...props\n}: Omit<PressableProps, \"onPress\"> & { style?: StyleProp<ViewStyle> }) {\n  const { theme, colors } = useTheme();\n  const { toggle } = useSidebar();\n  return (\n    <Pressable\n      accessibilityRole=\"button\"\n      accessibilityLabel=\"Toggle sidebar\"\n      onPress={toggle}\n      style={cn(\n        {\n          width: 36,\n          height: 36,\n          borderRadius: theme.radii.lg,\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          backgroundColor: colors.glassChromeBgEnv,\n          borderWidth: 1,\n          borderColor: colors.glassChromeBorder,\n        },\n        style,\n      )}\n      {...props}\n    >\n      <Text style={{ color: colors.foreground }}>☰</Text>\n    </Pressable>\n  );\n}\n\nexport function SidebarRail() {\n  return null;\n}\n\nexport const SidebarInset = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => (\n    <View ref={ref} style={cn({ flex: 1 }, style)} {...props} />\n  ),\n);\nSidebarInset.displayName = \"SidebarInset\";\n\nexport const SidebarHeader = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            gap: theme.spacing[2],\n            paddingBottom: theme.spacing[3],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nSidebarHeader.displayName = \"SidebarHeader\";\n\nexport const SidebarFooter = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            marginTop: \"auto\" as unknown as number,\n            gap: theme.spacing[2],\n            paddingTop: theme.spacing[3],\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nSidebarFooter.displayName = \"SidebarFooter\";\n\nexport const SidebarContent = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => (\n    <View ref={ref} style={cn({ flex: 1, gap: 4 }, style)} {...props} />\n  ),\n);\nSidebarContent.displayName = \"SidebarContent\";\n\nexport function SidebarSeparator(props: ViewProps) {\n  return <Separator {...props} />;\n}\n\nexport const SidebarGroup = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { theme } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn({ gap: theme.spacing[1], marginBottom: theme.spacing[3] }, style)}\n        {...props}\n      />\n    );\n  },\n);\nSidebarGroup.displayName = \"SidebarGroup\";\n\nexport const SidebarGroupLabel = forwardRef<Text, { children?: ReactNode; style?: StyleProp<ViewStyle> }>(\n  ({ children, style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            color: colors.mutedForeground,\n            fontSize: theme.fontSizes.xs,\n            fontWeight: theme.fontWeights.semibold,\n            textTransform: \"uppercase\",\n            paddingHorizontal: theme.spacing[2],\n            paddingVertical: theme.spacing[1],\n          },\n          style as object,\n        )}\n        {...props}\n      >\n        {children}\n      </Text>\n    );\n  },\n);\nSidebarGroupLabel.displayName = \"SidebarGroupLabel\";\n\nexport const SidebarGroupContent = forwardRef<View, ViewProps>((props, ref) => (\n  <View ref={ref} {...props} />\n));\nSidebarGroupContent.displayName = \"SidebarGroupContent\";\n\nexport const SidebarMenu = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => (\n    <View ref={ref} style={cn({ gap: 2 }, style)} {...props} />\n  ),\n);\nSidebarMenu.displayName = \"SidebarMenu\";\n\nexport const SidebarMenuItem = forwardRef<View, ViewProps>((props, ref) => (\n  <View ref={ref} {...props} />\n));\nSidebarMenuItem.displayName = \"SidebarMenuItem\";\n\nexport interface SidebarMenuButtonProps\n  extends Omit<PressableProps, \"children\"> {\n  isActive?: boolean;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const SidebarMenuButton = forwardRef<\n  React.ElementRef<typeof Pressable>,\n  SidebarMenuButtonProps\n>(({ isActive, children, style, ...props }, ref) => {\n  const { theme, colors } = useTheme();\n  return (\n    <Pressable\n      ref={ref}\n      accessibilityRole=\"button\"\n      accessibilityState={{ selected: !!isActive }}\n      style={cn(\n        {\n          flexDirection: \"row\",\n          alignItems: \"center\",\n          gap: theme.spacing[2],\n          paddingHorizontal: theme.spacing[3],\n          paddingVertical: theme.spacing[2.5],\n          borderRadius: theme.radii.lg,\n          backgroundColor: isActive ? colors.glassChromeBg : \"transparent\",\n        },\n        style,\n      )}\n      {...props}\n    >\n      {typeof children === \"string\" ? (\n        <Text\n          style={{\n            color: colors.foreground,\n            fontSize: theme.fontSizes.sm,\n            fontWeight: isActive\n              ? theme.fontWeights.semibold\n              : theme.fontWeights.medium,\n          }}\n        >\n          {children}\n        </Text>\n      ) : (\n        children\n      )}\n    </Pressable>\n  );\n});\nSidebarMenuButton.displayName = \"SidebarMenuButton\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "skeleton",
      "type": "registry:ui",
      "title": "Skeleton",
      "description": "React Native Skeleton for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/skeleton.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/skeleton.tsx",
          "content": "import { useEffect, useRef, forwardRef } from \"react\";\nimport {\n  Animated,\n  View,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type SkeletonVariant = \"default\" | \"chrome\" | \"text\";\nexport type SkeletonRounded = \"none\" | \"sm\" | \"md\" | \"lg\" | \"full\";\n\nexport interface SkeletonProps extends ViewProps {\n  variant?: SkeletonVariant;\n  animated?: boolean;\n  rounded?: SkeletonRounded;\n  style?: StyleProp<ViewStyle>;\n  width?: number | `${number}%`;\n  height?: number;\n}\n\nexport const Skeleton = forwardRef<View, SkeletonProps>(\n  (\n    {\n      variant = \"default\",\n      animated = true,\n      rounded = \"md\",\n      style,\n      width,\n      height,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const opacity = useRef(new Animated.Value(0.45)).current;\n\n    useEffect(() => {\n      if (!animated) return;\n      const loop = Animated.loop(\n        Animated.sequence([\n          Animated.timing(opacity, {\n            toValue: 1,\n            duration: 700,\n            useNativeDriver: true,\n          }),\n          Animated.timing(opacity, {\n            toValue: 0.45,\n            duration: 700,\n            useNativeDriver: true,\n          }),\n        ]),\n      );\n      loop.start();\n      return () => loop.stop();\n    }, [animated, opacity]);\n\n    const radiusMap = {\n      none: 0,\n      sm: theme.radii.sm,\n      md: theme.radii.md,\n      lg: theme.radii.lg,\n      full: theme.radii.full,\n    };\n\n    const bg =\n      variant === \"chrome\" ? colors.glassChromeBgEnv : colors.glassChromeBgEnv;\n\n    return (\n      <Animated.View\n        ref={ref}\n        style={cn(\n          {\n            backgroundColor: bg,\n            borderRadius: radiusMap[rounded],\n            opacity: animated ? opacity : 1,\n            width: width ?? (variant === \"text\" ? \"100%\" : undefined),\n            height: height ?? (variant === \"text\" ? 16 : undefined),\n            minHeight: height ?? (variant === \"text\" ? 16 : 12),\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nSkeleton.displayName = \"Skeleton\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "slider",
      "type": "registry:ui",
      "title": "Slider",
      "description": "React Native Slider for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/slider.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/slider.tsx",
          "content": "import { forwardRef, useMemo, useRef, useState } from \"react\";\nimport {\n  LayoutChangeEvent,\n  PanResponder,\n  View,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type SliderVariant = \"chrome\" | \"outline\";\nexport type SliderSize = \"sm\" | \"default\" | \"lg\";\n\nexport interface SliderProps extends ViewProps {\n  value?: number[];\n  defaultValue?: number[];\n  onValueChange?: (value: number[]) => void;\n  min?: number;\n  max?: number;\n  step?: number;\n  disabled?: boolean;\n  variant?: SliderVariant;\n  size?: SliderSize;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Slider = forwardRef<View, SliderProps>(\n  (\n    {\n      value: valueProp,\n      defaultValue = [0],\n      onValueChange,\n      min = 0,\n      max = 100,\n      step = 1,\n      disabled,\n      variant = \"chrome\",\n      size = \"default\",\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const isControlled = valueProp !== undefined;\n    const [internal, setInternal] = useState(defaultValue);\n    const values = isControlled ? valueProp! : internal;\n    const current = values[0] ?? min;\n\n    const trackWidth = useRef(0);\n    const trackHeight = size === \"sm\" ? 4 : size === \"lg\" ? 8 : 6;\n    const thumb = size === \"sm\" ? 16 : size === \"lg\" ? 24 : 20;\n\n    const setFromX = (x: number) => {\n      if (!trackWidth.current) return;\n      const ratio = Math.min(1, Math.max(0, x / trackWidth.current));\n      let next = min + ratio * (max - min);\n      if (step > 0) {\n        next = Math.round(next / step) * step;\n      }\n      next = Math.min(max, Math.max(min, next));\n      const arr = [next];\n      if (!isControlled) setInternal(arr);\n      onValueChange?.(arr);\n    };\n\n    const pan = useMemo(\n      () =>\n        PanResponder.create({\n          onStartShouldSetPanResponder: () => !disabled,\n          onMoveShouldSetPanResponder: () => !disabled,\n          onPanResponderGrant: (e) => setFromX(e.nativeEvent.locationX),\n          onPanResponderMove: (e) => setFromX(e.nativeEvent.locationX),\n        }),\n      // eslint-disable-next-line react-hooks/exhaustive-deps\n      [disabled, min, max, step, isControlled],\n    );\n\n    const pct = ((current - min) / (max - min || 1)) * 100;\n\n    return (\n      <View\n        ref={ref}\n        accessibilityRole=\"adjustable\"\n        accessibilityValue={{ min, max, now: current }}\n        onLayout={(e: LayoutChangeEvent) => {\n          trackWidth.current = e.nativeEvent.layout.width;\n        }}\n        style={cn(\n          {\n            height: thumb + 8,\n            justifyContent: \"center\",\n            opacity: disabled ? 0.5 : 1,\n            width: \"100%\",\n          },\n          style,\n        )}\n        {...pan.panHandlers}\n        {...props}\n      >\n        <View\n          style={{\n            height: trackHeight,\n            borderRadius: theme.radii.full,\n            backgroundColor:\n              variant === \"outline\"\n                ? colors.glassSurfaceFill\n                : colors.glassChromeBgEnv,\n            borderWidth: 1,\n            borderColor: colors.glassChromeBorder,\n            overflow: \"hidden\",\n          }}\n        >\n          <View\n            style={{\n              height: \"100%\",\n              width: `${pct}%`,\n              backgroundColor: colors.primary,\n              borderRadius: theme.radii.full,\n            }}\n          />\n        </View>\n        <View\n          pointerEvents=\"none\"\n          style={{\n            position: \"absolute\",\n            left: `${pct}%`,\n            marginLeft: -thumb / 2,\n            width: thumb,\n            height: thumb,\n            borderRadius: theme.radii.full,\n            backgroundColor: colors.glassIndicatorBg,\n            borderWidth: 1,\n            borderColor: colors.glassIndicatorBorder,\n          }}\n        />\n      </View>\n    );\n  },\n);\nSlider.displayName = \"Slider\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "spinner",
      "type": "registry:ui",
      "title": "Spinner",
      "description": "React Native Spinner for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/spinner.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/spinner.tsx",
          "content": "import {\n  forwardRef,\n  useEffect,\n  useRef,\n  type ReactNode,\n} from \"react\";\nimport {\n  ActivityIndicator,\n  Animated,\n  Easing,\n  View,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type SpinnerVariant = \"default\" | \"primary\" | \"muted\" | \"chrome\";\nexport type SpinnerSize = \"sm\" | \"default\" | \"lg\" | \"xl\";\n/** Visual spinner style. Color stays on `variant`. */\nexport type SpinnerType =\n  | \"default\"\n  | \"ring\"\n  | \"dots\"\n  | \"bars\"\n  | \"pulse\"\n  | \"apple\";\n\nexport interface SpinnerProps extends ViewProps {\n  variant?: SpinnerVariant;\n  size?: SpinnerSize;\n  type?: SpinnerType;\n  style?: StyleProp<ViewStyle>;\n}\n\nconst sizeMap: Record<SpinnerSize, \"small\" | \"large\"> = {\n  sm: \"small\",\n  default: \"small\",\n  lg: \"large\",\n  xl: \"large\",\n};\n\nconst dimMap: Record<SpinnerSize, number> = {\n  sm: 14,\n  default: 16,\n  lg: 24,\n  xl: 32,\n};\n\nfunction useLoop(\n  duration: number,\n  config?: { useNativeDriver?: boolean },\n) {\n  const value = useRef(new Animated.Value(0)).current;\n\n  useEffect(() => {\n    const loop = Animated.loop(\n      Animated.timing(value, {\n        toValue: 1,\n        duration,\n        easing: Easing.linear,\n        useNativeDriver: config?.useNativeDriver ?? true,\n      }),\n    );\n    loop.start();\n    return () => {\n      loop.stop();\n      value.setValue(0);\n    };\n  }, [duration, value, config?.useNativeDriver]);\n\n  return value;\n}\n\nfunction DotsSpinner({\n  color,\n  dim,\n}: {\n  color: string;\n  dim: number;\n}) {\n  const progress = useLoop(900);\n  const dots = [0, 1, 2] as const;\n\n  return (\n    <View\n      style={{\n        width: dim,\n        height: dim,\n        flexDirection: \"row\",\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        gap: Math.max(2, dim * 0.12),\n      }}\n    >\n      {dots.map((index) => {\n        const inputRange = [0, 0.2 + index * 0.15, 0.45 + index * 0.15, 1];\n        const translateY = progress.interpolate({\n          inputRange,\n          outputRange: [0, -dim * 0.22, 0, 0],\n          extrapolate: \"clamp\",\n        });\n        const opacity = progress.interpolate({\n          inputRange,\n          outputRange: [0.45, 1, 0.45, 0.45],\n          extrapolate: \"clamp\",\n        });\n        const size = Math.max(3, dim * 0.22);\n        return (\n          <Animated.View\n            key={index}\n            style={{\n              width: size,\n              height: size,\n              borderRadius: size / 2,\n              backgroundColor: color,\n              opacity,\n              transform: [{ translateY }],\n            }}\n          />\n        );\n      })}\n    </View>\n  );\n}\n\nfunction BarsSpinner({\n  color,\n  dim,\n}: {\n  color: string;\n  dim: number;\n}) {\n  const progress = useLoop(800);\n  const bars = [0, 1, 2] as const;\n\n  return (\n    <View\n      style={{\n        width: dim,\n        height: dim,\n        flexDirection: \"row\",\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        gap: Math.max(2, dim * 0.1),\n      }}\n    >\n      {bars.map((index) => {\n        const inputRange = [0, 0.2 + index * 0.12, 0.45 + index * 0.12, 1];\n        const scaleY = progress.interpolate({\n          inputRange,\n          outputRange: [0.35, 1, 0.35, 0.35],\n          extrapolate: \"clamp\",\n        });\n        const width = Math.max(2, dim * 0.16);\n        return (\n          <Animated.View\n            key={index}\n            style={{\n              width,\n              height: dim * 0.72,\n              borderRadius: width,\n              backgroundColor: color,\n              transform: [{ scaleY }],\n            }}\n          />\n        );\n      })}\n    </View>\n  );\n}\n\nfunction PulseSpinner({\n  color,\n  dim,\n}: {\n  color: string;\n  dim: number;\n}) {\n  const progress = useLoop(1100);\n\n  const scale = progress.interpolate({\n    inputRange: [0, 0.55, 1],\n    outputRange: [0.55, 1, 0.55],\n  });\n  const pingScale = progress.interpolate({\n    inputRange: [0, 1],\n    outputRange: [0.6, 1.35],\n  });\n  const pingOpacity = progress.interpolate({\n    inputRange: [0, 0.7, 1],\n    outputRange: [0.35, 0.08, 0],\n  });\n\n  return (\n    <View\n      style={{\n        width: dim,\n        height: dim,\n        alignItems: \"center\",\n        justifyContent: \"center\",\n      }}\n    >\n      <Animated.View\n        style={{\n          position: \"absolute\",\n          width: dim,\n          height: dim,\n          borderRadius: dim / 2,\n          backgroundColor: color,\n          opacity: pingOpacity,\n          transform: [{ scale: pingScale }],\n        }}\n      />\n      <Animated.View\n        style={{\n          width: dim * 0.45,\n          height: dim * 0.45,\n          borderRadius: dim,\n          backgroundColor: color,\n          transform: [{ scale }],\n        }}\n      />\n    </View>\n  );\n}\n\n/** Classic iOS-style 12-spoke activity indicator */\nfunction AppleSpinner({\n  color,\n  dim,\n}: {\n  color: string;\n  dim: number;\n}) {\n  const progress = useLoop(850);\n  const spokeCount = 12;\n  const spokeWidth = Math.max(1.5, dim * 0.12);\n  const spokeHeight = dim * 0.28;\n  const radius = dim * 0.5 - spokeHeight * 0.55;\n\n  const rotate = progress.interpolate({\n    inputRange: [0, 1],\n    outputRange: [\"0deg\", \"360deg\"],\n  });\n\n  return (\n    <Animated.View\n      style={{\n        width: dim,\n        height: dim,\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        transform: [{ rotate }],\n      }}\n    >\n      {Array.from({ length: spokeCount }, (_, index) => {\n        const angle = (index * 360) / spokeCount;\n        return (\n          <View\n            key={index}\n            style={{\n              position: \"absolute\",\n              width: spokeWidth,\n              height: spokeHeight,\n              borderRadius: spokeWidth,\n              backgroundColor: color,\n              opacity: 0.15 + (index / (spokeCount - 1)) * 0.85,\n              transform: [\n                { rotate: `${angle}deg` },\n                { translateY: -radius },\n              ],\n            }}\n          />\n        );\n      })}\n    </Animated.View>\n  );\n}\n\nexport const Spinner = forwardRef<View, SpinnerProps>(\n  (\n    {\n      variant = \"default\",\n      size = \"default\",\n      type = \"default\",\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const { colors } = useTheme();\n    const color =\n      variant === \"primary\"\n        ? colors.primary\n        : variant === \"muted\"\n          ? colors.mutedForeground\n          : variant === \"chrome\"\n            ? colors.glassChromeFg\n            : colors.foreground;\n    const dim = dimMap[size];\n\n    let body: ReactNode;\n    if (type === \"dots\") {\n      body = <DotsSpinner color={color} dim={dim} />;\n    } else if (type === \"bars\") {\n      body = <BarsSpinner color={color} dim={dim} />;\n    } else if (type === \"pulse\") {\n      body = <PulseSpinner color={color} dim={dim} />;\n    } else if (type === \"apple\") {\n      body = <AppleSpinner color={color} dim={dim} />;\n    } else {\n      // default + ring both use the platform indicator (single visual family)\n      body = <ActivityIndicator color={color} size={sizeMap[size]} />;\n    }\n\n    return (\n      <View\n        ref={ref}\n        accessibilityRole=\"progressbar\"\n        accessibilityLabel=\"Loading\"\n        accessibilityState={{ busy: true }}\n        style={cn(\n          {\n            width: dim,\n            height: dim,\n            alignItems: \"center\",\n            justifyContent: \"center\",\n          },\n          style,\n        )}\n        {...props}\n      >\n        {body}\n      </View>\n    );\n  },\n);\nSpinner.displayName = \"Spinner\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "stepper",
      "type": "registry:ui",
      "title": "Stepper",
      "description": "React Native Stepper for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/stepper.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/stepper.tsx",
          "content": "import { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport function Stepper({\n  steps,\n  current,\n}: {\n  steps: string[];\n  current: number;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ flexDirection: \"row\", alignItems: \"center\", gap: theme.spacing[2] }}>\n      {steps.map((step, i) => (\n        <View key={step} style={{ flex: 1, alignItems: \"center\", gap: 4 }}>\n          <View\n            style={{\n              width: 22,\n              height: 22,\n              borderRadius: 11,\n              alignItems: \"center\",\n              justifyContent: \"center\",\n              backgroundColor: i <= current ? colors.primary : colors.glassSurfaceFill,\n            }}\n          >\n            <Text\n              style={{\n                color: i <= current ? colors.primaryForeground : colors.mutedForeground,\n                fontSize: 11,\n              }}\n            >\n              {i + 1}\n            </Text>\n          </View>\n          <Text style={{ fontSize: 10, color: colors.mutedForeground }} numberOfLines={1}>\n            {step}\n          </Text>\n        </View>\n      ))}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "switch",
      "type": "registry:ui",
      "title": "Switch",
      "description": "React Native Switch for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/switch.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/switch.tsx",
          "content": "import { forwardRef, useEffect, useRef, useState } from \"react\";\nimport {\n  Animated,\n  Pressable,\n  type PressableProps,\n  type StyleProp,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { springs } from \"../utils/animation\";\nimport { cn } from \"../utils/cn\";\n\nexport type SwitchVariant = \"chrome\" | \"outline\";\nexport type SwitchSize = \"sm\" | \"default\" | \"lg\";\n\nexport interface SwitchProps extends Omit<PressableProps, \"onPress\"> {\n  checked?: boolean;\n  defaultChecked?: boolean;\n  onCheckedChange?: (checked: boolean) => void;\n  variant?: SwitchVariant;\n  size?: SwitchSize;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Switch = forwardRef<React.ElementRef<typeof Pressable>, SwitchProps>(\n  (\n    {\n      checked: checkedProp,\n      defaultChecked = false,\n      onCheckedChange,\n      variant = \"chrome\",\n      size = \"default\",\n      disabled,\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const isControlled = checkedProp !== undefined;\n    const [internal, setInternal] = useState(defaultChecked);\n    const checked = isControlled ? !!checkedProp : internal;\n\n    const dims =\n      size === \"sm\"\n        ? { w: 36, h: 20, thumb: 14, travel: 16 }\n        : size === \"lg\"\n          ? { w: 52, h: 28, thumb: 24, travel: 22 }\n          : { w: 44, h: 24, thumb: 20, travel: 18 };\n\n    const anim = useRef(new Animated.Value(checked ? 1 : 0)).current;\n\n    useEffect(() => {\n      Animated.spring(anim, {\n        toValue: checked ? 1 : 0,\n        ...springs.thumb,\n      }).start();\n    }, [checked, anim]);\n\n    const trackBg = checked\n      ? variant === \"outline\"\n        ? colors.primary\n        : colors.primary\n      : variant === \"outline\"\n        ? colors.glassSurfaceFill\n        : colors.glassChromeBgEnv;\n\n    return (\n      <Pressable\n        ref={ref}\n        accessibilityRole=\"switch\"\n        accessibilityState={{ checked, disabled: !!disabled }}\n        disabled={disabled}\n        onPress={() => {\n          const next = !checked;\n          if (!isControlled) setInternal(next);\n          onCheckedChange?.(next);\n        }}\n        style={cn(\n          {\n            width: dims.w,\n            height: dims.h,\n            borderRadius: theme.radii.full,\n            borderWidth: 1,\n            borderColor: checked\n              ? \"rgba(26,26,26,0.25)\"\n              : colors.glassChromeBorder,\n            backgroundColor: trackBg,\n            justifyContent: \"center\",\n            opacity: disabled ? 0.5 : 1,\n            paddingHorizontal: 2,\n          },\n          style,\n        )}\n        {...props}\n      >\n        <Animated.View\n          style={{\n            width: dims.thumb,\n            height: dims.thumb,\n            borderRadius: theme.radii.full,\n            backgroundColor: colors.glassIndicatorBg,\n            borderWidth: 1,\n            borderColor: colors.glassIndicatorBorder,\n            transform: [\n              {\n                translateX: anim.interpolate({\n                  inputRange: [0, 1],\n                  outputRange: [0, dims.travel],\n                }),\n              },\n            ],\n          }}\n        />\n      </Pressable>\n    );\n  },\n);\nSwitch.displayName = \"Switch\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "table",
      "type": "registry:ui",
      "title": "Table",
      "description": "React Native Table for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/table.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/table.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  ScrollView,\n  Text,\n  View,\n  type StyleProp,\n  type TextProps,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type TableDensity = \"compact\" | \"default\" | \"comfortable\";\n\nexport interface TableProps extends ViewProps {\n  density?: TableDensity;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Table = forwardRef<ScrollView, TableProps>(\n  ({ density = \"default\", children, style, ...props }, ref) => {\n    const { colors } = useTheme();\n    return (\n      <ScrollView\n        ref={ref}\n        horizontal\n        style={cn(\n          {\n            width: \"100%\",\n            borderWidth: 1,\n            borderColor: colors.glassChromeBorder,\n            borderRadius: 12,\n          },\n          style,\n        )}\n        contentContainerStyle={{ flexGrow: 1 }}\n        {...props}\n      >\n        <View style={{ minWidth: \"100%\" }} data-density={density}>\n          {children}\n        </View>\n      </ScrollView>\n    );\n  },\n);\nTable.displayName = \"Table\";\n\nexport const TableHeader = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { colors } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            borderBottomWidth: 1,\n            borderBottomColor: colors.glassChromeBorder,\n            backgroundColor: colors.glassChromeBgEnv,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nTableHeader.displayName = \"TableHeader\";\n\nexport const TableBody = forwardRef<View, ViewProps>((props, ref) => (\n  <View ref={ref} {...props} />\n));\nTableBody.displayName = \"TableBody\";\n\nexport const TableFooter = forwardRef<View, ViewProps>(\n  ({ style, ...props }, ref) => {\n    const { colors } = useTheme();\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            borderTopWidth: 1,\n            borderTopColor: colors.glassChromeBorder,\n            backgroundColor: colors.glassChromeBgEnv,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nTableFooter.displayName = \"TableFooter\";\n\nexport const TableRow = forwardRef<View, ViewProps>(({ style, ...props }, ref) => {\n  const { colors } = useTheme();\n  return (\n    <View\n      ref={ref}\n      style={cn(\n        {\n          flexDirection: \"row\",\n          borderBottomWidth: StyleSheetHairline,\n          borderBottomColor: colors.border,\n          alignItems: \"center\",\n        },\n        style,\n      )}\n      {...props}\n    />\n  );\n});\nTableRow.displayName = \"TableRow\";\n\nconst StyleSheetHairline = 1;\n\nexport const TableHead = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            flex: 1,\n            paddingHorizontal: theme.spacing[3],\n            paddingVertical: theme.spacing[3],\n            color: colors.mutedForeground,\n            fontSize: theme.fontSizes.xs,\n            fontWeight: theme.fontWeights.semibold,\n            textTransform: \"uppercase\",\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nTableHead.displayName = \"TableHead\";\n\nexport const TableCell = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            flex: 1,\n            paddingHorizontal: theme.spacing[3],\n            paddingVertical: theme.spacing[3],\n            color: colors.foreground,\n            fontSize: theme.fontSizes.sm,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nTableCell.displayName = \"TableCell\";\n\nexport const TableCaption = forwardRef<Text, TextProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    return (\n      <Text\n        ref={ref}\n        style={cn(\n          {\n            marginTop: theme.spacing[2],\n            color: colors.mutedForeground,\n            fontSize: theme.fontSizes.sm,\n            textAlign: \"center\",\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nTableCaption.displayName = \"TableCaption\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "tabs",
      "type": "registry:ui",
      "title": "Tabs",
      "description": "React Native Tabs for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/tabs.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/tabs.tsx",
          "content": "import {\n  createContext,\n  forwardRef,\n  useContext,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  Pressable,\n  Text,\n  View,\n  type PressableProps,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\ninterface TabsContextValue {\n  value?: string;\n  onValueChange?: (value: string) => void;\n  size: \"sm\" | \"default\" | \"lg\";\n  variant: \"chrome\" | \"plain\";\n}\n\nconst TabsContext = createContext<TabsContextValue>({\n  size: \"default\",\n  variant: \"chrome\",\n});\n\nexport interface TabsProps extends ViewProps {\n  value?: string;\n  defaultValue?: string;\n  onValueChange?: (value: string) => void;\n  size?: \"sm\" | \"default\" | \"lg\";\n  variant?: \"chrome\" | \"plain\";\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Tabs = forwardRef<View, TabsProps>(\n  (\n    {\n      value: valueProp,\n      defaultValue,\n      onValueChange,\n      size = \"default\",\n      variant = \"chrome\",\n      children,\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const isControlled = valueProp !== undefined;\n    const [internal, setInternal] = useState(defaultValue);\n    const value = isControlled ? valueProp : internal;\n\n    return (\n      <TabsContext.Provider\n        value={{\n          value,\n          onValueChange: (v) => {\n            if (!isControlled) setInternal(v);\n            onValueChange?.(v);\n          },\n          size,\n          variant,\n        }}\n      >\n        <View ref={ref} style={style} {...props}>\n          {children}\n        </View>\n      </TabsContext.Provider>\n    );\n  },\n);\nTabs.displayName = \"Tabs\";\n\nexport interface TabsListProps extends ViewProps {\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const TabsList = forwardRef<View, TabsListProps>(\n  ({ style, ...props }, ref) => {\n    const { theme, colors } = useTheme();\n    const ctx = useContext(TabsContext);\n    const height = ctx.size === \"sm\" ? 36 : ctx.size === \"lg\" ? 44 : 40;\n\n    return (\n      <View\n        ref={ref}\n        style={cn(\n          {\n            flexDirection: \"row\",\n            alignItems: \"center\",\n            gap: theme.spacing[1],\n            padding: theme.spacing[1],\n            height,\n            borderRadius: theme.radii[\"2xl\"],\n            backgroundColor:\n              ctx.variant === \"chrome\"\n                ? colors.glassChromeBgEnv\n                : colors.glassSurfaceFill,\n            borderWidth: 1,\n            borderColor: colors.glassChromeBorder,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nTabsList.displayName = \"TabsList\";\n\nexport interface TabsTriggerProps extends Omit<PressableProps, \"children\"> {\n  value: string;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const TabsTrigger = forwardRef<\n  React.ElementRef<typeof Pressable>,\n  TabsTriggerProps\n>(({ value, children, style, ...props }, ref) => {\n  const { theme, colors } = useTheme();\n  const ctx = useContext(TabsContext);\n  const active = ctx.value === value;\n  const fontSize =\n    ctx.size === \"sm\" ? theme.fontSizes.xs : theme.fontSizes.sm;\n\n  return (\n    <Pressable\n      ref={ref}\n      accessibilityRole=\"tab\"\n      accessibilityState={{ selected: active }}\n      onPress={() => ctx.onValueChange?.(value)}\n      style={cn(\n        {\n          flex: 1,\n          height: \"100%\",\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          borderRadius: theme.radii.xl,\n          paddingHorizontal: theme.spacing[3],\n          backgroundColor: active ? colors.glassIndicatorBg : \"transparent\",\n        },\n        style,\n      )}\n      {...props}\n    >\n      {typeof children === \"string\" ? (\n        <Text\n          style={{\n            color: active ? colors.foreground : colors.mutedForeground,\n            fontSize,\n            fontWeight: active\n              ? theme.fontWeights.semibold\n              : theme.fontWeights.medium,\n          }}\n        >\n          {children}\n        </Text>\n      ) : (\n        children\n      )}\n    </Pressable>\n  );\n});\nTabsTrigger.displayName = \"TabsTrigger\";\n\nexport interface TabsContentProps extends ViewProps {\n  value: string;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const TabsContent = forwardRef<View, TabsContentProps>(\n  ({ value, style, children, ...props }, ref) => {\n    const ctx = useContext(TabsContext);\n    const { theme } = useTheme();\n    if (ctx.value !== value) return null;\n    return (\n      <View\n        ref={ref}\n        style={cn({ marginTop: theme.spacing[4] }, style)}\n        {...props}\n      >\n        {children}\n      </View>\n    );\n  },\n);\nTabsContent.displayName = \"TabsContent\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "textarea",
      "type": "registry:ui",
      "title": "Textarea",
      "description": "React Native Textarea for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/textarea.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/textarea.tsx",
          "content": "import { forwardRef } from \"react\";\nimport {\n  TextInput,\n  type StyleProp,\n  type TextInputProps,\n  type TextStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\nimport type { FieldSize, FieldState, FieldVariant } from \"./input\";\n\nexport interface TextareaProps extends TextInputProps {\n  variant?: FieldVariant;\n  size?: FieldSize;\n  state?: FieldState;\n  style?: StyleProp<TextStyle>;\n}\n\nexport const Textarea = forwardRef<TextInput, TextareaProps>(\n  (\n    {\n      variant = \"chrome\",\n      size = \"default\",\n      state = \"default\",\n      style,\n      placeholderTextColor,\n      editable = true,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const minHeight = size === \"sm\" ? 72 : size === \"lg\" ? 104 : 88;\n    const fontSize =\n      size === \"sm\"\n        ? theme.fontSizes.xs\n        : size === \"lg\"\n          ? theme.fontSizes.base\n          : theme.fontSizes.sm;\n\n    const borderColor =\n      state === \"error\"\n        ? colors.destructive\n        : state === \"success\"\n          ? colors.success\n          : colors.glassChromeBorder;\n\n    return (\n      <TextInput\n        ref={ref}\n        multiline\n        textAlignVertical=\"top\"\n        editable={editable}\n        placeholderTextColor={\n          placeholderTextColor ?? colors.glassChromeFgMuted\n        }\n        style={cn(\n          {\n            width: \"100%\",\n            minHeight,\n            borderRadius: theme.radii.xl,\n            paddingHorizontal: size === \"lg\" ? theme.spacing[4] : theme.spacing[3],\n            paddingVertical: size === \"lg\" ? theme.spacing[3] : theme.spacing[2.5],\n            fontSize,\n            color: colors.glassChromeFg,\n            backgroundColor:\n              variant === \"outline\"\n                ? colors.glassSurfaceFill\n                : colors.glassChromeBgEnv,\n            borderWidth: 1,\n            borderColor,\n            opacity: editable === false ? 0.5 : 1,\n          },\n          style,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nTextarea.displayName = \"Textarea\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "theme-toggle",
      "type": "registry:ui",
      "title": "Theme Toggle",
      "description": "React Native Theme Toggle for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "button"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/theme-toggle.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/theme-toggle.tsx",
          "content": "import { Button, type ButtonProps } from \"./button\";\nimport { useTheme } from \"../theme\";\n\nexport type ThemeToggleProps = Omit<ButtonProps, \"onPress\" | \"children\">;\n\nexport function ThemeToggle(props: ThemeToggleProps) {\n  const { mode, toggleMode } = useTheme();\n  return (\n    <Button\n      variant=\"outline\"\n      size=\"icon\"\n      shape=\"pill\"\n      accessibilityLabel=\"Toggle color mode\"\n      onPress={toggleMode}\n      {...props}\n    >\n      {mode === \"dark\" ? \"☀\" : \"☾\"}\n    </Button>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "time-picker",
      "type": "registry:ui",
      "title": "Time Picker",
      "description": "React Native Time Picker for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input",
        "calendar"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/time-picker.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/time-picker.tsx",
          "content": "import { Input } from \"./input\";\nimport { Calendar } from \"./calendar\";\n\nexport function TimePicker({\n  value,\n  onChange,\n}: {\n  value?: string;\n  onChange?: (value: string) => void;\n}) {\n  return (\n    <Input\n      placeholder=\"09:30\"\n      keyboardType=\"numbers-and-punctuation\"\n      value={value}\n      onChangeText={onChange}\n    />\n  );\n}\n\nexport function MonthPicker({\n  value,\n  onChange,\n}: {\n  value?: Date;\n  onChange?: (value: Date | undefined) => void;\n}) {\n  return (\n    <Calendar\n      mode=\"single\"\n      selected={value}\n      onSelect={(next) => onChange?.(next instanceof Date ? next : undefined)}\n    />\n  );\n}\n\nexport function DateTimePicker({\n  date,\n  time,\n  onDateChange,\n  onTimeChange,\n}: {\n  date?: Date;\n  time?: string;\n  onDateChange?: (value: Date | undefined) => void;\n  onTimeChange?: (value: string) => void;\n}) {\n  return (\n    <>\n      <Calendar\n        mode=\"single\"\n        selected={date}\n        onSelect={(next) => onDateChange?.(next instanceof Date ? next : undefined)}\n      />\n      <TimePicker value={time} onChange={onTimeChange} />\n    </>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "month-picker",
      "type": "registry:ui",
      "title": "Month Picker",
      "description": "React Native Month Picker for Expo, iOS, and Android.",
      "dependencies": [
        "date-fns"
      ],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input",
        "calendar"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/time-picker.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/time-picker.tsx",
          "content": "import { Input } from \"./input\";\nimport { Calendar } from \"./calendar\";\n\nexport function TimePicker({\n  value,\n  onChange,\n}: {\n  value?: string;\n  onChange?: (value: string) => void;\n}) {\n  return (\n    <Input\n      placeholder=\"09:30\"\n      keyboardType=\"numbers-and-punctuation\"\n      value={value}\n      onChangeText={onChange}\n    />\n  );\n}\n\nexport function MonthPicker({\n  value,\n  onChange,\n}: {\n  value?: Date;\n  onChange?: (value: Date | undefined) => void;\n}) {\n  return (\n    <Calendar\n      mode=\"single\"\n      selected={value}\n      onSelect={(next) => onChange?.(next instanceof Date ? next : undefined)}\n    />\n  );\n}\n\nexport function DateTimePicker({\n  date,\n  time,\n  onDateChange,\n  onTimeChange,\n}: {\n  date?: Date;\n  time?: string;\n  onDateChange?: (value: Date | undefined) => void;\n  onTimeChange?: (value: string) => void;\n}) {\n  return (\n    <>\n      <Calendar\n        mode=\"single\"\n        selected={date}\n        onSelect={(next) => onDateChange?.(next instanceof Date ? next : undefined)}\n      />\n      <TimePicker value={time} onChange={onTimeChange} />\n    </>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "date-time-picker",
      "type": "registry:ui",
      "title": "Date Time Picker",
      "description": "React Native Date Time Picker for Expo, iOS, and Android.",
      "dependencies": [
        "date-fns"
      ],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "input",
        "calendar"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/time-picker.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/time-picker.tsx",
          "content": "import { Input } from \"./input\";\nimport { Calendar } from \"./calendar\";\n\nexport function TimePicker({\n  value,\n  onChange,\n}: {\n  value?: string;\n  onChange?: (value: string) => void;\n}) {\n  return (\n    <Input\n      placeholder=\"09:30\"\n      keyboardType=\"numbers-and-punctuation\"\n      value={value}\n      onChangeText={onChange}\n    />\n  );\n}\n\nexport function MonthPicker({\n  value,\n  onChange,\n}: {\n  value?: Date;\n  onChange?: (value: Date | undefined) => void;\n}) {\n  return (\n    <Calendar\n      mode=\"single\"\n      selected={value}\n      onSelect={(next) => onChange?.(next instanceof Date ? next : undefined)}\n    />\n  );\n}\n\nexport function DateTimePicker({\n  date,\n  time,\n  onDateChange,\n  onTimeChange,\n}: {\n  date?: Date;\n  time?: string;\n  onDateChange?: (value: Date | undefined) => void;\n  onTimeChange?: (value: string) => void;\n}) {\n  return (\n    <>\n      <Calendar\n        mode=\"single\"\n        selected={date}\n        onSelect={(next) => onDateChange?.(next instanceof Date ? next : undefined)}\n      />\n      <TimePicker value={time} onChange={onTimeChange} />\n    </>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "timeline",
      "type": "registry:ui",
      "title": "Timeline",
      "description": "React Native Timeline for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/timeline.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/timeline.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport function Timeline({\n  items,\n}: {\n  items: Array<{ title: string; description?: string; time?: string }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[4] }}>\n      {items.map((item, i) => (\n        <View key={`${item.title}-${i}`} style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n          <View style={{ alignItems: \"center\" }}>\n            <View\n              style={{\n                width: 10,\n                height: 10,\n                borderRadius: 5,\n                backgroundColor: colors.primary,\n                marginTop: 4,\n              }}\n            />\n            {i < items.length - 1 ? (\n              <View\n                style={{\n                  width: 1,\n                  flex: 1,\n                  backgroundColor: colors.glassChromeBorder,\n                  marginTop: 4,\n                }}\n              />\n            ) : null}\n          </View>\n          <View style={{ flex: 1, paddingBottom: theme.spacing[3] }}>\n            <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.medium }}>\n              {item.title}\n            </Text>\n            {item.time ? (\n              <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n                {item.time}\n              </Text>\n            ) : null}\n            {item.description ? (\n              <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n                {item.description}\n              </Text>\n            ) : null}\n          </View>\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function ActivityFeed(props: {\n  items: Array<{ title: string; description?: string; time?: string }>;\n}) {\n  return <Timeline {...props} />;\n}\n\nexport function NotificationCenter({\n  children,\n}: {\n  children?: ReactNode;\n}) {\n  return <View>{children}</View>;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "activity-feed",
      "type": "registry:ui",
      "title": "Activity Feed",
      "description": "React Native Activity Feed for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/timeline.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/timeline.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport function Timeline({\n  items,\n}: {\n  items: Array<{ title: string; description?: string; time?: string }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[4] }}>\n      {items.map((item, i) => (\n        <View key={`${item.title}-${i}`} style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n          <View style={{ alignItems: \"center\" }}>\n            <View\n              style={{\n                width: 10,\n                height: 10,\n                borderRadius: 5,\n                backgroundColor: colors.primary,\n                marginTop: 4,\n              }}\n            />\n            {i < items.length - 1 ? (\n              <View\n                style={{\n                  width: 1,\n                  flex: 1,\n                  backgroundColor: colors.glassChromeBorder,\n                  marginTop: 4,\n                }}\n              />\n            ) : null}\n          </View>\n          <View style={{ flex: 1, paddingBottom: theme.spacing[3] }}>\n            <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.medium }}>\n              {item.title}\n            </Text>\n            {item.time ? (\n              <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n                {item.time}\n              </Text>\n            ) : null}\n            {item.description ? (\n              <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n                {item.description}\n              </Text>\n            ) : null}\n          </View>\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function ActivityFeed(props: {\n  items: Array<{ title: string; description?: string; time?: string }>;\n}) {\n  return <Timeline {...props} />;\n}\n\nexport function NotificationCenter({\n  children,\n}: {\n  children?: ReactNode;\n}) {\n  return <View>{children}</View>;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "notification-center",
      "type": "registry:ui",
      "title": "Notification Center",
      "description": "React Native Notification Center for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/timeline.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/timeline.tsx",
          "content": "import { type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\nexport function Timeline({\n  items,\n}: {\n  items: Array<{ title: string; description?: string; time?: string }>;\n}) {\n  const { theme, colors } = useTheme();\n  return (\n    <View style={{ gap: theme.spacing[4] }}>\n      {items.map((item, i) => (\n        <View key={`${item.title}-${i}`} style={{ flexDirection: \"row\", gap: theme.spacing[3] }}>\n          <View style={{ alignItems: \"center\" }}>\n            <View\n              style={{\n                width: 10,\n                height: 10,\n                borderRadius: 5,\n                backgroundColor: colors.primary,\n                marginTop: 4,\n              }}\n            />\n            {i < items.length - 1 ? (\n              <View\n                style={{\n                  width: 1,\n                  flex: 1,\n                  backgroundColor: colors.glassChromeBorder,\n                  marginTop: 4,\n                }}\n              />\n            ) : null}\n          </View>\n          <View style={{ flex: 1, paddingBottom: theme.spacing[3] }}>\n            <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.medium }}>\n              {item.title}\n            </Text>\n            {item.time ? (\n              <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.xs }}>\n                {item.time}\n              </Text>\n            ) : null}\n            {item.description ? (\n              <Text style={{ color: colors.mutedForeground, fontSize: theme.fontSizes.sm }}>\n                {item.description}\n              </Text>\n            ) : null}\n          </View>\n        </View>\n      ))}\n    </View>\n  );\n}\n\nexport function ActivityFeed(props: {\n  items: Array<{ title: string; description?: string; time?: string }>;\n}) {\n  return <Timeline {...props} />;\n}\n\nexport function NotificationCenter({\n  children,\n}: {\n  children?: ReactNode;\n}) {\n  return <View>{children}</View>;\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "toast",
      "type": "registry:ui",
      "title": "Toast",
      "description": "React Native Toast for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/toast.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/toast.tsx",
          "content": "import { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\n\ntype ToastItem = { id: number; title: string; description?: string };\n\nconst ToastContext = createContext<{\n  toast: (item: Omit<ToastItem, \"id\">) => void;\n} | null>(null);\n\nexport function useToast() {\n  const ctx = useContext(ToastContext);\n  if (!ctx) throw new Error(\"useToast must be used within ToastProvider\");\n  return ctx;\n}\n\nexport function ToastProvider({ children }: { children: ReactNode }) {\n  const { theme, colors } = useTheme();\n  const [items, setItems] = useState<ToastItem[]>([]);\n  const toast = useCallback((item: Omit<ToastItem, \"id\">) => {\n    const id = Date.now();\n    setItems((prev) => [...prev, { id, ...item }]);\n    setTimeout(() => setItems((prev) => prev.filter((t) => t.id !== id)), 2800);\n  }, []);\n  const value = useMemo(() => ({ toast }), [toast]);\n\n  return (\n    <ToastContext.Provider value={value}>\n      {children}\n      <View\n        pointerEvents=\"none\"\n        style={{\n          position: \"absolute\",\n          left: theme.spacing[4],\n          right: theme.spacing[4],\n          bottom: theme.spacing[8],\n          gap: theme.spacing[2],\n        }}\n      >\n        {items.map((item) => (\n          <View\n            key={item.id}\n            style={{\n              borderRadius: theme.radii.xl,\n              padding: theme.spacing[3],\n              backgroundColor: colors.glassChromeBgEnv,\n              borderWidth: 1,\n              borderColor: colors.glassChromeBorder,\n            }}\n          >\n            <Text style={{ color: colors.foreground, fontWeight: theme.fontWeights.semibold }}>\n              {item.title}\n            </Text>\n            {item.description ? (\n              <Text style={{ color: colors.mutedForeground, marginTop: 2 }}>\n                {item.description}\n              </Text>\n            ) : null}\n          </View>\n        ))}\n      </View>\n    </ToastContext.Provider>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "toggle-group",
      "type": "registry:ui",
      "title": "Toggle Group",
      "description": "React Native Toggle Group for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/toggle-group.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/toggle-group.tsx",
          "content": "import {\n  createContext,\n  forwardRef,\n  useContext,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  Pressable,\n  Text,\n  View,\n  type PressableProps,\n  type StyleProp,\n  type ViewProps,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\ntype ToggleGroupType = \"single\" | \"multiple\";\n\ninterface ToggleGroupContextValue {\n  type: ToggleGroupType;\n  value: string[];\n  onItemPress: (value: string) => void;\n  size: \"sm\" | \"default\" | \"lg\";\n  variant: \"default\" | \"outline\" | \"chrome\";\n  disabled?: boolean;\n}\n\nconst ToggleGroupContext = createContext<ToggleGroupContextValue | null>(null);\n\nexport interface ToggleGroupProps extends ViewProps {\n  type?: ToggleGroupType;\n  value?: string | string[];\n  defaultValue?: string | string[];\n  onValueChange?: (value: string | string[]) => void;\n  size?: \"sm\" | \"default\" | \"lg\";\n  variant?: \"default\" | \"outline\" | \"chrome\";\n  disabled?: boolean;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nfunction toArray(v?: string | string[]): string[] {\n  if (v == null) return [];\n  return Array.isArray(v) ? v : [v];\n}\n\nexport const ToggleGroup = forwardRef<View, ToggleGroupProps>(\n  (\n    {\n      type = \"single\",\n      value: valueProp,\n      defaultValue,\n      onValueChange,\n      size = \"default\",\n      variant = \"default\",\n      disabled,\n      children,\n      style,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const isControlled = valueProp !== undefined;\n    const [internal, setInternal] = useState(toArray(defaultValue));\n    const value = isControlled ? toArray(valueProp) : internal;\n\n    const onItemPress = (item: string) => {\n      let next: string[];\n      if (type === \"single\") {\n        next = value.includes(item) ? [] : [item];\n      } else {\n        next = value.includes(item)\n          ? value.filter((v) => v !== item)\n          : [...value, item];\n      }\n      if (!isControlled) setInternal(next);\n      onValueChange?.(type === \"single\" ? (next[0] ?? \"\") : next);\n    };\n\n    return (\n      <ToggleGroupContext.Provider\n        value={{ type, value, onItemPress, size, variant, disabled }}\n      >\n        <View\n          ref={ref}\n          style={cn(\n            {\n              flexDirection: \"row\",\n              alignItems: \"center\",\n              gap: theme.spacing[1],\n              padding: theme.spacing[1],\n              borderRadius: theme.radii.xl,\n              backgroundColor: colors.glassChromeBgEnv,\n              borderWidth: 1,\n              borderColor: colors.glassChromeBorder,\n            },\n            style,\n          )}\n          {...props}\n        >\n          {children}\n        </View>\n      </ToggleGroupContext.Provider>\n    );\n  },\n);\nToggleGroup.displayName = \"ToggleGroup\";\n\nexport interface ToggleGroupItemProps\n  extends Omit<PressableProps, \"children\"> {\n  value: string;\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const ToggleGroupItem = forwardRef<\n  React.ElementRef<typeof Pressable>,\n  ToggleGroupItemProps\n>(({ value, children, disabled, style, ...props }, ref) => {\n  const { theme, colors } = useTheme();\n  const ctx = useContext(ToggleGroupContext);\n  if (!ctx) throw new Error(\"ToggleGroupItem must be used within ToggleGroup\");\n\n  const selected = ctx.value.includes(value);\n  const isDisabled = disabled || ctx.disabled;\n  const height = ctx.size === \"sm\" ? 28 : ctx.size === \"lg\" ? 36 : 32;\n  const fontSize =\n    ctx.size === \"sm\" ? theme.fontSizes.xs : theme.fontSizes.sm;\n\n  return (\n    <Pressable\n      ref={ref}\n      accessibilityRole=\"button\"\n      accessibilityState={{ selected, disabled: !!isDisabled }}\n      disabled={isDisabled}\n      onPress={() => ctx.onItemPress(value)}\n      style={cn(\n        {\n          height,\n          paddingHorizontal: theme.spacing[3],\n          borderRadius: theme.radii.lg,\n          backgroundColor: selected ? colors.primary : \"transparent\",\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          opacity: isDisabled ? 0.5 : 1,\n        },\n        style,\n      )}\n      {...props}\n    >\n      {typeof children === \"string\" ? (\n        <Text\n          style={{\n            color: selected ? colors.primaryForeground : colors.foreground,\n            fontSize,\n            fontWeight: theme.fontWeights.medium,\n          }}\n        >\n          {children}\n        </Text>\n      ) : (\n        children\n      )}\n    </Pressable>\n  );\n});\nToggleGroupItem.displayName = \"ToggleGroupItem\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "toggle",
      "type": "registry:ui",
      "title": "Toggle",
      "description": "React Native Toggle for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/toggle.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/toggle.tsx",
          "content": "import { forwardRef, useState, type ReactNode } from \"react\";\nimport {\n  Animated,\n  Pressable,\n  Text,\n  type PressableProps,\n  type StyleProp,\n  type TextStyle,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { usePressScale } from \"../utils/animation\";\nimport { cn } from \"../utils/cn\";\nimport { pressedOpacity } from \"../utils/pressable\";\n\nexport type ToggleVariant = \"default\" | \"outline\" | \"chrome\";\nexport type ToggleSize = \"sm\" | \"default\" | \"lg\";\n\nexport interface ToggleProps extends Omit<PressableProps, \"children\"> {\n  pressed?: boolean;\n  defaultPressed?: boolean;\n  onPressedChange?: (pressed: boolean) => void;\n  variant?: ToggleVariant;\n  size?: ToggleSize;\n  children?: ReactNode;\n  textStyle?: StyleProp<TextStyle>;\n  style?: StyleProp<ViewStyle>;\n}\n\nexport const Toggle = forwardRef<\n  React.ElementRef<typeof Pressable>,\n  ToggleProps\n>(\n  (\n    {\n      pressed: pressedProp,\n      defaultPressed = false,\n      onPressedChange,\n      variant = \"default\",\n      size = \"default\",\n      disabled,\n      children,\n      textStyle,\n      style,\n      onPressIn,\n      onPressOut,\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, colors } = useTheme();\n    const isControlled = pressedProp !== undefined;\n    const [internal, setInternal] = useState(defaultPressed);\n    const isPressed = isControlled ? !!pressedProp : internal;\n    const press = usePressScale({ pressedScale: 0.96, disabled: !!disabled });\n\n    const height = size === \"sm\" ? 32 : size === \"lg\" ? 40 : 36;\n    const padH = size === \"sm\" ? 10 : size === \"lg\" ? 16 : 12;\n    const fontSize =\n      size === \"sm\" ? theme.fontSizes.xs : theme.fontSizes.sm;\n\n    const bg = isPressed\n      ? colors.primary\n      : variant === \"outline\" || variant === \"chrome\"\n        ? colors.glassChromeBgEnv\n        : \"transparent\";\n\n    const fg = isPressed ? colors.primaryForeground : colors.foreground;\n\n    return (\n      <Animated.View style={press.style}>\n        <Pressable\n          ref={ref}\n          accessibilityRole=\"button\"\n          accessibilityState={{ selected: isPressed, disabled: !!disabled }}\n          disabled={disabled}\n          onPressIn={(e) => {\n            press.onPressIn();\n            onPressIn?.(e);\n          }}\n          onPressOut={(e) => {\n            press.onPressOut();\n            onPressOut?.(e);\n          }}\n          onPress={() => {\n            const next = !isPressed;\n            if (!isControlled) setInternal(next);\n            onPressedChange?.(next);\n          }}\n          style={({ pressed }) =>\n            cn(\n              {\n                height,\n                paddingHorizontal: padH,\n                borderRadius: theme.radii.lg,\n                borderWidth: variant === \"outline\" || variant === \"chrome\" ? 1 : 0,\n                borderColor: colors.glassChromeBorder,\n                backgroundColor: bg,\n                alignItems: \"center\",\n                justifyContent: \"center\",\n                opacity: pressedOpacity(pressed) * (disabled ? 0.5 : 1),\n              },\n              style,\n            )\n          }\n          {...props}\n        >\n          {typeof children === \"string\" ? (\n            <Text\n              style={cn(\n                {\n                  color: fg,\n                  fontSize,\n                  fontWeight: theme.fontWeights.medium,\n                },\n                textStyle,\n              )}\n            >\n              {children}\n            </Text>\n          ) : (\n            children\n          )}\n        </Pressable>\n      </Animated.View>\n    );\n  },\n);\nToggle.displayName = \"Toggle\";\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "tooltip",
      "type": "registry:ui",
      "title": "Tooltip",
      "description": "React Native Tooltip for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/tooltip.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/tooltip.tsx",
          "content": "import {\n  createContext,\n  useContext,\n  useEffect,\n  useRef,\n  useState,\n  type ReactNode,\n} from \"react\";\nimport {\n  Modal,\n  Pressable,\n  Text,\n  View,\n  type StyleProp,\n  type ViewStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\ninterface TooltipContextValue {\n  open: boolean;\n  setOpen: (open: boolean) => void;\n  content: ReactNode;\n  setContent: (c: ReactNode) => void;\n}\n\nconst TooltipContext = createContext<TooltipContextValue | null>(null);\n\nfunction useTooltip() {\n  const ctx = useContext(TooltipContext);\n  if (!ctx) throw new Error(\"Tooltip components must be used within Tooltip\");\n  return ctx;\n}\n\nexport function TooltipProvider({ children }: { children?: ReactNode }) {\n  return <>{children}</>;\n}\n\nexport interface TooltipProps {\n  children?: ReactNode;\n  delayDuration?: number;\n}\n\nexport function Tooltip({ children }: TooltipProps) {\n  const [open, setOpen] = useState(false);\n  const [content, setContent] = useState<ReactNode>(null);\n  return (\n    <TooltipContext.Provider value={{ open, setOpen, content, setContent }}>\n      {children}\n      <TooltipModal />\n    </TooltipContext.Provider>\n  );\n}\n\nexport function TooltipTrigger({\n  children,\n  delayDuration = 400,\n}: {\n  children?: ReactNode;\n  delayDuration?: number;\n}) {\n  const { setOpen } = useTooltip();\n  const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n  return (\n    <Pressable\n      onLongPress={() => setOpen(true)}\n      onPressIn={() => {\n        timer.current = setTimeout(() => setOpen(true), delayDuration);\n      }}\n      onPressOut={() => {\n        if (timer.current) clearTimeout(timer.current);\n        setOpen(false);\n      }}\n      delayLongPress={delayDuration}\n    >\n      {children}\n    </Pressable>\n  );\n}\n\nexport interface TooltipContentProps {\n  children?: ReactNode;\n  style?: StyleProp<ViewStyle>;\n  side?: \"top\" | \"bottom\";\n}\n\nexport function TooltipContent({ children }: TooltipContentProps) {\n  const { setContent } = useTooltip();\n  useEffect(() => {\n    setContent(children);\n  }, [children, setContent]);\n  return null;\n}\n\nfunction TooltipModal() {\n  const { theme, colors } = useTheme();\n  const ctx = useContext(TooltipContext);\n  if (!ctx) return null;\n\n  return (\n    <Modal\n      visible={ctx.open}\n      transparent\n      animationType=\"fade\"\n      onRequestClose={() => ctx.setOpen(false)}\n    >\n      <Pressable\n        style={{\n          flex: 1,\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          padding: theme.spacing[6],\n        }}\n        onPress={() => ctx.setOpen(false)}\n      >\n        <View\n          style={cn({\n            backgroundColor: colors.popover,\n            borderRadius: theme.radii.lg,\n            borderWidth: 1,\n            borderColor: colors.glassChromeBorder,\n            paddingHorizontal: theme.spacing[3],\n            paddingVertical: theme.spacing[2],\n            maxWidth: 280,\n          })}\n        >\n          {typeof ctx.content === \"string\" ? (\n            <Text\n              style={{\n                color: colors.popoverForeground,\n                fontSize: theme.fontSizes.sm,\n              }}\n            >\n              {ctx.content}\n            </Text>\n          ) : (\n            ctx.content\n          )}\n        </View>\n      </Pressable>\n    </Modal>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "typography",
      "type": "registry:ui",
      "title": "Typography",
      "description": "React Native Typography for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/typography.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/typography.tsx",
          "content": "import { forwardRef, type ReactNode } from \"react\";\nimport {\n  Text,\n  type StyleProp,\n  type TextProps,\n  type TextStyle,\n} from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { cn } from \"../utils/cn\";\n\nexport type TypographyColorVariant = \"default\" | \"chrome\" | \"muted\";\n\nexport interface TypographyProps extends TextProps {\n  variant?: TypographyColorVariant;\n  children?: ReactNode;\n  style?: StyleProp<TextStyle>;\n}\n\nfunction useTypographyColor(variant: TypographyColorVariant = \"default\") {\n  const { colors } = useTheme();\n  if (variant === \"chrome\") return colors.glassChromeFg;\n  if (variant === \"muted\") return colors.mutedForeground;\n  return colors.foreground;\n}\n\nfunction createTypography(\n  name: string,\n  base: (theme: ReturnType<typeof useTheme>[\"theme\"]) => TextStyle,\n) {\n  const Comp = forwardRef<Text, TypographyProps>(\n    ({ variant = \"default\", style, children, ...props }, ref) => {\n      const { theme } = useTheme();\n      const color = useTypographyColor(variant);\n      return (\n        <Text\n          ref={ref}\n          style={cn({ color, ...base(theme) }, style)}\n          {...props}\n        >\n          {children}\n        </Text>\n      );\n    },\n  );\n  Comp.displayName = name;\n  return Comp;\n}\n\nexport const TypographyH1 = createTypography(\"TypographyH1\", (t) => ({\n  fontSize: t.fontSizes[\"4xl\"],\n  fontWeight: t.fontWeights.extrabold,\n  letterSpacing: -0.5,\n  lineHeight: t.fontSizes[\"4xl\"] * t.lineHeights.tight,\n}));\n\nexport const TypographyH2 = createTypography(\"TypographyH2\", (t) => ({\n  fontSize: t.fontSizes[\"3xl\"],\n  fontWeight: t.fontWeights.semibold,\n  letterSpacing: -0.3,\n  lineHeight: t.fontSizes[\"3xl\"] * t.lineHeights.tight,\n}));\n\nexport const TypographyH3 = createTypography(\"TypographyH3\", (t) => ({\n  fontSize: t.fontSizes[\"2xl\"],\n  fontWeight: t.fontWeights.semibold,\n  lineHeight: t.fontSizes[\"2xl\"] * t.lineHeights.snug,\n}));\n\nexport const TypographyH4 = createTypography(\"TypographyH4\", (t) => ({\n  fontSize: t.fontSizes.xl,\n  fontWeight: t.fontWeights.semibold,\n  lineHeight: t.fontSizes.xl * t.lineHeights.snug,\n}));\n\nexport const TypographyP = createTypography(\"TypographyP\", (t) => ({\n  fontSize: t.fontSizes.base,\n  lineHeight: t.fontSizes.base * t.lineHeights.relaxed,\n  marginBottom: t.spacing[4],\n}));\n\nexport const TypographyBlockquote = createTypography(\n  \"TypographyBlockquote\",\n  (t) => ({\n    fontSize: t.fontSizes.base,\n    fontStyle: \"italic\",\n    borderLeftWidth: 3,\n    paddingLeft: t.spacing[4],\n    opacity: 0.9,\n  }),\n);\n\nexport const TypographyInlineCode = createTypography(\n  \"TypographyInlineCode\",\n  (t) => ({\n    fontSize: t.fontSizes.sm,\n    fontFamily: \"Menlo\",\n    paddingHorizontal: 4,\n    paddingVertical: 2,\n  }),\n);\n\nexport const TypographyLead = createTypography(\"TypographyLead\", (t) => ({\n  fontSize: t.fontSizes.xl,\n  lineHeight: t.fontSizes.xl * t.lineHeights.relaxed,\n}));\n\nexport const TypographyLarge = createTypography(\"TypographyLarge\", (t) => ({\n  fontSize: t.fontSizes.lg,\n  fontWeight: t.fontWeights.semibold,\n}));\n\nexport const TypographySmall = createTypography(\"TypographySmall\", (t) => ({\n  fontSize: t.fontSizes.sm,\n  fontWeight: t.fontWeights.medium,\n  lineHeight: t.fontSizes.sm * t.lineHeights.normal,\n}));\n\nexport const TypographyMuted = createTypography(\"TypographyMuted\", (t) => ({\n  fontSize: t.fontSizes.sm,\n  lineHeight: t.fontSizes.sm * t.lineHeights.normal,\n}));\n\nexport const TypographyList = createTypography(\"TypographyList\", (t) => ({\n  fontSize: t.fontSizes.base,\n  lineHeight: t.fontSizes.base * t.lineHeights.relaxed,\n  marginLeft: t.spacing[4],\n}));\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "code-viewer",
      "type": "registry:ui",
      "title": "Code Viewer",
      "description": "React Native Code Viewer for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "scroll-area",
        "textarea",
        "markdown-viewer"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/viewers.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/viewers.tsx",
          "content": "import { useState, type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { ScrollArea } from \"./scroll-area\";\nimport { Textarea } from \"./textarea\";\nimport { MarkdownViewer } from \"./markdown-viewer\";\n\nexport function CodeViewer({ code }: { code: string }) {\n  const { colors, theme } = useTheme();\n  return (\n    <ScrollArea style={{ maxHeight: 220 }}>\n      <Text\n        selectable\n        style={{\n          fontFamily: \"Menlo\",\n          fontSize: theme.fontSizes.xs,\n          color: colors.foreground,\n        }}\n      >\n        {code}\n      </Text>\n    </ScrollArea>\n  );\n}\n\nexport function JsonViewer({ value }: { value: unknown }) {\n  return <CodeViewer code={JSON.stringify(value, null, 2)} />;\n}\n\nexport function TerminalBlock({ lines }: { lines: string[] }) {\n  return <CodeViewer code={lines.join(\"\\n\")} />;\n}\n\nexport function MarkdownEditor({\n  value,\n  onChange,\n}: {\n  value: string;\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  const [tab, setTab] = useState<\"write\" | \"preview\">(\"write\");\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {tab === \"write\" ? (\n        <Textarea value={value} onChangeText={onChange} />\n      ) : (\n        <MarkdownViewer content={value} />\n      )}\n      <Text\n        onPress={() => setTab(tab === \"write\" ? \"preview\" : \"write\")}\n        style={{ textAlign: \"right\" }}\n      >\n        {tab === \"write\" ? \"Preview\" : \"Write\"}\n      </Text>\n    </View>\n  );\n}\n\nexport function ComponentPreview({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        borderRadius: theme.radii.xl,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        padding: theme.spacing[4],\n      }}\n    >\n      {children}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "json-viewer",
      "type": "registry:ui",
      "title": "Json Viewer",
      "description": "React Native Json Viewer for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "scroll-area",
        "textarea",
        "markdown-viewer"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/viewers.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/viewers.tsx",
          "content": "import { useState, type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { ScrollArea } from \"./scroll-area\";\nimport { Textarea } from \"./textarea\";\nimport { MarkdownViewer } from \"./markdown-viewer\";\n\nexport function CodeViewer({ code }: { code: string }) {\n  const { colors, theme } = useTheme();\n  return (\n    <ScrollArea style={{ maxHeight: 220 }}>\n      <Text\n        selectable\n        style={{\n          fontFamily: \"Menlo\",\n          fontSize: theme.fontSizes.xs,\n          color: colors.foreground,\n        }}\n      >\n        {code}\n      </Text>\n    </ScrollArea>\n  );\n}\n\nexport function JsonViewer({ value }: { value: unknown }) {\n  return <CodeViewer code={JSON.stringify(value, null, 2)} />;\n}\n\nexport function TerminalBlock({ lines }: { lines: string[] }) {\n  return <CodeViewer code={lines.join(\"\\n\")} />;\n}\n\nexport function MarkdownEditor({\n  value,\n  onChange,\n}: {\n  value: string;\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  const [tab, setTab] = useState<\"write\" | \"preview\">(\"write\");\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {tab === \"write\" ? (\n        <Textarea value={value} onChangeText={onChange} />\n      ) : (\n        <MarkdownViewer content={value} />\n      )}\n      <Text\n        onPress={() => setTab(tab === \"write\" ? \"preview\" : \"write\")}\n        style={{ textAlign: \"right\" }}\n      >\n        {tab === \"write\" ? \"Preview\" : \"Write\"}\n      </Text>\n    </View>\n  );\n}\n\nexport function ComponentPreview({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        borderRadius: theme.radii.xl,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        padding: theme.spacing[4],\n      }}\n    >\n      {children}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "terminal-block",
      "type": "registry:ui",
      "title": "Terminal Block",
      "description": "React Native Terminal Block for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "scroll-area",
        "textarea",
        "markdown-viewer"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/viewers.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/viewers.tsx",
          "content": "import { useState, type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { ScrollArea } from \"./scroll-area\";\nimport { Textarea } from \"./textarea\";\nimport { MarkdownViewer } from \"./markdown-viewer\";\n\nexport function CodeViewer({ code }: { code: string }) {\n  const { colors, theme } = useTheme();\n  return (\n    <ScrollArea style={{ maxHeight: 220 }}>\n      <Text\n        selectable\n        style={{\n          fontFamily: \"Menlo\",\n          fontSize: theme.fontSizes.xs,\n          color: colors.foreground,\n        }}\n      >\n        {code}\n      </Text>\n    </ScrollArea>\n  );\n}\n\nexport function JsonViewer({ value }: { value: unknown }) {\n  return <CodeViewer code={JSON.stringify(value, null, 2)} />;\n}\n\nexport function TerminalBlock({ lines }: { lines: string[] }) {\n  return <CodeViewer code={lines.join(\"\\n\")} />;\n}\n\nexport function MarkdownEditor({\n  value,\n  onChange,\n}: {\n  value: string;\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  const [tab, setTab] = useState<\"write\" | \"preview\">(\"write\");\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {tab === \"write\" ? (\n        <Textarea value={value} onChangeText={onChange} />\n      ) : (\n        <MarkdownViewer content={value} />\n      )}\n      <Text\n        onPress={() => setTab(tab === \"write\" ? \"preview\" : \"write\")}\n        style={{ textAlign: \"right\" }}\n      >\n        {tab === \"write\" ? \"Preview\" : \"Write\"}\n      </Text>\n    </View>\n  );\n}\n\nexport function ComponentPreview({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        borderRadius: theme.radii.xl,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        padding: theme.spacing[4],\n      }}\n    >\n      {children}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "markdown-editor",
      "type": "registry:ui",
      "title": "Markdown Editor",
      "description": "React Native Markdown Editor for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "scroll-area",
        "textarea",
        "markdown-viewer"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/viewers.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/viewers.tsx",
          "content": "import { useState, type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { ScrollArea } from \"./scroll-area\";\nimport { Textarea } from \"./textarea\";\nimport { MarkdownViewer } from \"./markdown-viewer\";\n\nexport function CodeViewer({ code }: { code: string }) {\n  const { colors, theme } = useTheme();\n  return (\n    <ScrollArea style={{ maxHeight: 220 }}>\n      <Text\n        selectable\n        style={{\n          fontFamily: \"Menlo\",\n          fontSize: theme.fontSizes.xs,\n          color: colors.foreground,\n        }}\n      >\n        {code}\n      </Text>\n    </ScrollArea>\n  );\n}\n\nexport function JsonViewer({ value }: { value: unknown }) {\n  return <CodeViewer code={JSON.stringify(value, null, 2)} />;\n}\n\nexport function TerminalBlock({ lines }: { lines: string[] }) {\n  return <CodeViewer code={lines.join(\"\\n\")} />;\n}\n\nexport function MarkdownEditor({\n  value,\n  onChange,\n}: {\n  value: string;\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  const [tab, setTab] = useState<\"write\" | \"preview\">(\"write\");\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {tab === \"write\" ? (\n        <Textarea value={value} onChangeText={onChange} />\n      ) : (\n        <MarkdownViewer content={value} />\n      )}\n      <Text\n        onPress={() => setTab(tab === \"write\" ? \"preview\" : \"write\")}\n        style={{ textAlign: \"right\" }}\n      >\n        {tab === \"write\" ? \"Preview\" : \"Write\"}\n      </Text>\n    </View>\n  );\n}\n\nexport function ComponentPreview({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        borderRadius: theme.radii.xl,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        padding: theme.spacing[4],\n      }}\n    >\n      {children}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    },
    {
      "name": "component-preview",
      "type": "registry:ui",
      "title": "Component Preview",
      "description": "React Native Component Preview for Expo, iOS, and Android.",
      "dependencies": [],
      "registryDependencies": [
        "native-theme",
        "native-utils",
        "scroll-area",
        "textarea",
        "markdown-viewer"
      ],
      "files": [
        {
          "path": "packages/ui-native/src/components/viewers.tsx",
          "type": "registry:ui",
          "target": "components/ui/native/viewers.tsx",
          "content": "import { useState, type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { ScrollArea } from \"./scroll-area\";\nimport { Textarea } from \"./textarea\";\nimport { MarkdownViewer } from \"./markdown-viewer\";\n\nexport function CodeViewer({ code }: { code: string }) {\n  const { colors, theme } = useTheme();\n  return (\n    <ScrollArea style={{ maxHeight: 220 }}>\n      <Text\n        selectable\n        style={{\n          fontFamily: \"Menlo\",\n          fontSize: theme.fontSizes.xs,\n          color: colors.foreground,\n        }}\n      >\n        {code}\n      </Text>\n    </ScrollArea>\n  );\n}\n\nexport function JsonViewer({ value }: { value: unknown }) {\n  return <CodeViewer code={JSON.stringify(value, null, 2)} />;\n}\n\nexport function TerminalBlock({ lines }: { lines: string[] }) {\n  return <CodeViewer code={lines.join(\"\\n\")} />;\n}\n\nexport function MarkdownEditor({\n  value,\n  onChange,\n}: {\n  value: string;\n  onChange?: (v: string) => void;\n}) {\n  const { theme } = useTheme();\n  const [tab, setTab] = useState<\"write\" | \"preview\">(\"write\");\n  return (\n    <View style={{ gap: theme.spacing[2] }}>\n      {tab === \"write\" ? (\n        <Textarea value={value} onChangeText={onChange} />\n      ) : (\n        <MarkdownViewer content={value} />\n      )}\n      <Text\n        onPress={() => setTab(tab === \"write\" ? \"preview\" : \"write\")}\n        style={{ textAlign: \"right\" }}\n      >\n        {tab === \"write\" ? \"Preview\" : \"Write\"}\n      </Text>\n    </View>\n  );\n}\n\nexport function ComponentPreview({ children }: { children?: ReactNode }) {\n  const { theme, colors } = useTheme();\n  return (\n    <View\n      style={{\n        borderRadius: theme.radii.xl,\n        borderWidth: 1,\n        borderColor: colors.glassChromeBorder,\n        padding: theme.spacing[4],\n      }}\n    >\n      {children}\n    </View>\n  );\n}\n"
        }
      ],
      "meta": {
        "platform": "native"
      }
    }
  ]
}
