about summary refs log tree commit diff
path: root/src/components/Toast/index.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/Toast/index.tsx')
-rw-r--r--src/components/Toast/index.tsx57
1 files changed, 50 insertions, 7 deletions
diff --git a/src/components/Toast/index.tsx b/src/components/Toast/index.tsx
index 286d414a1..16d62afcd 100644
--- a/src/components/Toast/index.tsx
+++ b/src/components/Toast/index.tsx
@@ -1,15 +1,21 @@
+import React from 'react'
 import {View} from 'react-native'
+import {nanoid} from 'nanoid/non-secure'
 import {toast as sonner, Toaster} from 'sonner-native'
 
 import {atoms as a} from '#/alf'
 import {DURATION} from '#/components/Toast/const'
 import {
-  Toast as BaseToast,
+  Default as DefaultToast,
+  Outer as BaseOuter,
   type ToastComponentProps,
+  ToastConfigProvider,
 } from '#/components/Toast/Toast'
 import {type BaseToastOptions} from '#/components/Toast/types'
 
 export {DURATION} from '#/components/Toast/const'
+export {Action, Icon, Text} from '#/components/Toast/Toast'
+export {type ToastType} from '#/components/Toast/types'
 
 /**
  * Toasts are rendered in a global outlet, which is placed at the top of the
@@ -22,10 +28,24 @@ export function ToastOutlet() {
 /**
  * The toast UI component
  */
-export function Toast({type, content}: ToastComponentProps) {
+export function Default({type, content}: ToastComponentProps) {
   return (
     <View style={[a.px_xl, a.w_full]}>
-      <BaseToast content={content} type={type} />
+      <DefaultToast content={content} type={type} />
+    </View>
+  )
+}
+
+export function Outer({
+  children,
+  type = 'default',
+}: {
+  children: React.ReactNode
+  type?: ToastComponentProps['type']
+}) {
+  return (
+    <View style={[a.px_xl, a.w_full]}>
+      <BaseOuter type={type}>{children}</BaseOuter>
     </View>
   )
 }
@@ -42,8 +62,31 @@ export function show(
   content: React.ReactNode,
   {type, ...options}: BaseToastOptions = {},
 ) {
-  sonner.custom(<Toast content={content} type={type} />, {
-    ...options,
-    duration: options?.duration ?? DURATION,
-  })
+  const id = nanoid()
+
+  if (typeof content === 'string') {
+    sonner.custom(
+      <ToastConfigProvider id={id}>
+        <DefaultToast content={content} type={type} />
+      </ToastConfigProvider>,
+      {
+        ...options,
+        id,
+        duration: options?.duration ?? DURATION,
+      },
+    )
+  } else if (React.isValidElement(content)) {
+    sonner.custom(
+      <ToastConfigProvider id={id}>{content}</ToastConfigProvider>,
+      {
+        ...options,
+        id,
+        duration: options?.duration ?? DURATION,
+      },
+    )
+  } else {
+    throw new Error(
+      `Toast can be a string or a React element, got ${typeof content}`,
+    )
+  }
 }