{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "toast",
  "title": "Toast",
  "description": "An opinionated toast component for React Native.",
  "dependencies": [
    "sonner-native",
    "react-native-gesture-handler",
    "react-native-reanimated",
    "react-native-safe-area-context",
    "react-native-screens",
    "react-native-svg",
    "react-native-worklets"
  ],
  "registryDependencies": [
    "@tetra-ui/icons",
    "@tetra-ui/text"
  ],
  "files": [
    {
      "path": "ui/toast.tsx",
      "content": "import { cva } from \"class-variance-authority\";\nimport { ActivityIndicator, View } from \"react-native\";\nimport * as ToastPrimitive from \"sonner-native\";\nimport { useUniwind } from \"uniwind\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  CircleAlertIcon,\n  CircleCheckIcon,\n  InfoIcon,\n  TriangleAlertIcon,\n} from \"./icons\";\nimport { Text } from \"./text\";\n\n// Types\ntype ToastVariant =\n  | \"default\"\n  | \"success\"\n  | \"error\"\n  | \"warning\"\n  | \"info\"\n  | \"loading\";\n\ntype ToastIconProps = {\n  variant: ToastVariant;\n};\n\ntype ToastOptions = NonNullable<\n  Parameters<typeof ToastPrimitive.toast.custom>[1]\n>;\n\ntype PromiseOptions = {\n  loading: string;\n  success: string | ((result: unknown) => string);\n  error: string | ((error: unknown) => string);\n} & Omit<ToastOptions, \"description\" | \"icon\">;\n\n// Components\nconst ToastIcon = ({ variant }: ToastIconProps) => {\n  const iconClassName = iconVariants({ variant });\n\n  if (variant === \"loading\") {\n    return (\n      <View className=\"size-5 items-center justify-center\">\n        <ActivityIndicator className=\"accent-muted-foreground\" size=\"small\" />\n      </View>\n    );\n  }\n\n  if (variant === \"success\") {\n    return <CircleCheckIcon className={iconClassName} />;\n  }\n\n  if (variant === \"error\") {\n    return <TriangleAlertIcon className={iconClassName} />;\n  }\n\n  if (variant === \"warning\") {\n    return <CircleAlertIcon className={iconClassName} />;\n  }\n\n  return <InfoIcon className={iconClassName} />;\n};\n\ntype TetraToastProps = {\n  variant: ToastVariant;\n  title: string;\n  description?: string;\n  icon?: React.ReactNode;\n};\n\nconst TetraToast = ({ variant, title, description, icon }: TetraToastProps) => (\n  <View className=\"mx-4 justify-center rounded-2xl border border-border/80 bg-popover p-4 shadow-md\">\n    <View\n      className={cn(\n        \"flex-row gap-4\",\n        description ? \"items-start\" : \"items-center\"\n      )}\n    >\n      {icon ?? <ToastIcon variant={variant} />}\n      <View className=\"flex-1\">\n        <Text className={titleVariants({ variant })}>{title}</Text>\n        {description ? (\n          <Text className=\"text-muted-foreground text-sm\">{description}</Text>\n        ) : null}\n      </View>\n    </View>\n  </View>\n);\n\nexport const Toaster = (props: Omit<ToastPrimitive.ToasterProps, \"theme\">) => {\n  const { theme: uniwindTheme } = useUniwind();\n  const theme = uniwindTheme === \"dark\" ? \"dark\" : \"light\";\n\n  return (\n    <ToastPrimitive.Toaster {...props} enableStacking gap={4} theme={theme} />\n  );\n};\n\n// Utils\nconst showToast = (\n  variant: ToastVariant,\n  title: string,\n  options?: ToastOptions\n) => {\n  const { description, icon, ...rest } = options ?? {};\n\n  return ToastPrimitive.toast.custom(\n    <TetraToast\n      description={description}\n      icon={icon}\n      title={title}\n      variant={variant}\n    />,\n    rest\n  );\n};\n\nexport const toast = Object.assign(\n  (message: string, options?: ToastOptions) =>\n    showToast(\"default\", message, options),\n  {\n    custom: ToastPrimitive.toast.custom,\n    dismiss: ToastPrimitive.toast.dismiss,\n    error: (message: string, options?: ToastOptions) =>\n      showToast(\"error\", message, options),\n    info: (message: string, options?: ToastOptions) =>\n      showToast(\"info\", message, options),\n    loading: (message: string, options?: ToastOptions) =>\n      showToast(\"loading\", message, options),\n    promise: <T,>(promise: Promise<T>, options: PromiseOptions) => {\n      const { loading, success, error, ...rest } = options;\n      const id = ToastPrimitive.toast.custom(\n        <TetraToast title={loading} variant=\"loading\" />,\n        { ...rest, duration: Number.POSITIVE_INFINITY }\n      );\n\n      promise\n        .then((data) => {\n          const title = typeof success === \"function\" ? success(data) : success;\n          ToastPrimitive.toast.custom(\n            <TetraToast title={title} variant=\"success\" />,\n            {\n              duration: rest.duration,\n              id,\n            }\n          );\n        })\n        .catch((err) => {\n          const title = typeof error === \"function\" ? error(err) : error;\n          ToastPrimitive.toast.custom(\n            <TetraToast title={title} variant=\"error\" />,\n            {\n              duration: rest.duration,\n              id,\n            }\n          );\n        });\n\n      return id;\n    },\n    success: (message: string, options?: ToastOptions) =>\n      showToast(\"success\", message, options),\n    warning: (message: string, options?: ToastOptions) =>\n      showToast(\"warning\", message, options),\n    wiggle: ToastPrimitive.toast.wiggle,\n  }\n);\n\n// Styles\nconst titleVariants = cva(\"font-semibold leading-5\", {\n  variants: {\n    variant: {\n      default: \"text-popover-foreground\",\n      error: \"text-destructive\",\n      info: \"text-info\",\n      loading: \"text-popover-foreground\",\n      success: \"text-success\",\n      warning: \"text-warning\",\n    },\n  },\n});\n\nconst iconVariants = cva(\"size-5\", {\n  variants: {\n    variant: {\n      default: \"text-muted-foreground\",\n      error: \"text-destructive\",\n      info: \"text-info\",\n      loading: \"text-muted-foreground\",\n      success: \"text-success\",\n      warning: \"text-warning\",\n    },\n  },\n});\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}
