@@ -15,6 +15,7 @@ import { ToastItemRenderer } from './toast-item-renderer';
1515import type {
1616 ToastComponentProps ,
1717 ToasterContextValue ,
18+ ToastGlobalConfig ,
1819 ToastProviderProps ,
1920 ToastShowConfig ,
2021 ToastShowOptions ,
@@ -28,50 +29,116 @@ const DEFAULT_DURATION = 4000;
2829 */
2930const ToasterContext = createContext < ToasterContextValue | null > ( null ) ;
3031
32+ /**
33+ * Context for global toast configuration
34+ */
35+ const ToastConfigContext = createContext < ToastGlobalConfig | undefined > (
36+ undefined
37+ ) ;
38+
39+ /**
40+ * Merges global config with local config, ensuring local config takes precedence
41+ * Only includes defined values from localConfig to avoid overriding global config with undefined
42+ */
43+ function mergeToastConfig (
44+ globalConfig : ToastGlobalConfig | undefined ,
45+ localConfig : Partial < ToastGlobalConfig >
46+ ) : Partial < ToastGlobalConfig > {
47+ const result : Partial < ToastGlobalConfig > = { ...globalConfig } ;
48+
49+ // Only override with defined values from localConfig
50+ if ( localConfig . variant !== undefined ) {
51+ result . variant = localConfig . variant ;
52+ }
53+ if ( localConfig . placement !== undefined ) {
54+ result . placement = localConfig . placement ;
55+ }
56+ if ( localConfig . isSwipeable !== undefined ) {
57+ result . isSwipeable = localConfig . isSwipeable ;
58+ }
59+ if ( localConfig . animation !== undefined ) {
60+ result . animation = localConfig . animation ;
61+ }
62+
63+ return result ;
64+ }
65+
3166/**
3267 * Creates a component function for simple string toast
3368 */
3469function createStringToastComponent (
35- label : string
70+ label : string ,
71+ globalConfig : ToastGlobalConfig | undefined
3672) : ( props : ToastComponentProps ) => React . ReactElement {
37- return ( props : ToastComponentProps ) => (
38- < DefaultToast { ...props } label = { label } variant = "default" />
39- ) ;
73+ return ( props : ToastComponentProps ) => {
74+ const mergedConfig = mergeToastConfig ( globalConfig , {
75+ variant : 'default' ,
76+ } ) ;
77+ return (
78+ < DefaultToast
79+ { ...props }
80+ label = { label }
81+ variant = { mergedConfig . variant }
82+ placement = { mergedConfig . placement }
83+ isSwipeable = { mergedConfig . isSwipeable }
84+ animation = { mergedConfig . animation }
85+ />
86+ ) ;
87+ } ;
4088}
4189
4290/**
4391 * Creates a component function for config-based toast
4492 */
4593function createConfigToastComponent (
46- config : ToastShowConfig
94+ config : ToastShowConfig ,
95+ globalConfig : ToastGlobalConfig | undefined
4796) : ( props : ToastComponentProps ) => React . ReactElement {
48- return ( props : ToastComponentProps ) => (
49- < DefaultToast
50- { ...props }
51- variant = { config . variant }
52- placement = { config . placement }
53- isSwipeable = { config . isSwipeable }
54- label = { config . label }
55- description = { config . description }
56- actionLabel = { config . actionLabel }
57- onActionPress = { config . onActionPress }
58- icon = { config . icon }
59- />
60- ) ;
97+ return ( props : ToastComponentProps ) => {
98+ const mergedConfig = mergeToastConfig ( globalConfig , {
99+ variant : config . variant ,
100+ placement : config . placement ,
101+ isSwipeable : config . isSwipeable ,
102+ animation : config . animation ,
103+ } ) ;
104+ return (
105+ < DefaultToast
106+ { ...props }
107+ variant = { mergedConfig . variant }
108+ placement = { mergedConfig . placement }
109+ isSwipeable = { mergedConfig . isSwipeable }
110+ animation = { mergedConfig . animation }
111+ label = { config . label }
112+ description = { config . description }
113+ actionLabel = { config . actionLabel }
114+ onActionPress = { config . onActionPress }
115+ icon = { config . icon }
116+ />
117+ ) ;
118+ } ;
61119}
62120
63121/**
64122 * Toast provider component
65123 * Wraps your app to enable toast functionality
66124 */
67125export function ToastProvider ( {
126+ defaultProps,
68127 insets,
69128 maxVisibleToasts = 3 ,
70129 contentWrapper,
71130 children,
72131} : ToastProviderProps ) {
73132 const [ toasts , dispatch ] = useReducer ( toastReducer , [ ] ) ;
74133
134+ /**
135+ * Memoize global config to prevent unnecessary re-renders
136+ */
137+ const globalConfig = useMemo < ToastGlobalConfig | undefined > (
138+ ( ) => defaultProps ,
139+ [ defaultProps ]
140+ ) ;
141+
75142 const isToastVisible = toasts . length > 0 ;
76143
77144 const heights = useSharedValue < Record < string , number > > ( { } ) ;
@@ -206,7 +273,7 @@ export function ToastProvider({
206273 if ( typeof options === 'string' ) {
207274 normalizedOptions = {
208275 id : undefined ,
209- component : createStringToastComponent ( options ) ,
276+ component : createStringToastComponent ( options , globalConfig ) ,
210277 duration : DEFAULT_DURATION ,
211278 } ;
212279 duration = DEFAULT_DURATION ;
@@ -219,7 +286,7 @@ export function ToastProvider({
219286 explicitId = config . id ;
220287 normalizedOptions = {
221288 id : config . id ,
222- component : createConfigToastComponent ( config ) ,
289+ component : createConfigToastComponent ( config , globalConfig ) ,
223290 duration,
224291 onShow : config . onShow ,
225292 onHide : config . onHide ,
@@ -289,7 +356,7 @@ export function ToastProvider({
289356
290357 return id ;
291358 } ,
292- [ total , toasts ]
359+ [ total , toasts , globalConfig ]
293360 ) ;
294361
295362 const contextValue = useMemo < ToasterContextValue > (
@@ -304,25 +371,27 @@ export function ToastProvider({
304371 ) ;
305372
306373 return (
307- < ToasterContext . Provider value = { contextValue } >
308- { children }
309- < InsetsContainer insets = { insets } contentWrapper = { contentWrapper } >
310- < View className = "flex-1" >
311- { toasts . map ( ( toastItem , index ) => (
312- < ToastItemRenderer
313- key = { toastItem . id }
314- toastItem = { toastItem }
315- show = { show }
316- hide = { hide }
317- index = { index }
318- total = { total }
319- heights = { heights }
320- maxVisibleToasts = { maxVisibleToasts }
321- />
322- ) ) }
323- </ View >
324- </ InsetsContainer >
325- </ ToasterContext . Provider >
374+ < ToastConfigContext . Provider value = { globalConfig } >
375+ < ToasterContext . Provider value = { contextValue } >
376+ { children }
377+ < InsetsContainer insets = { insets } contentWrapper = { contentWrapper } >
378+ < View className = "flex-1" >
379+ { toasts . map ( ( toastItem , index ) => (
380+ < ToastItemRenderer
381+ key = { toastItem . id }
382+ toastItem = { toastItem }
383+ show = { show }
384+ hide = { hide }
385+ index = { index }
386+ total = { total }
387+ heights = { heights }
388+ maxVisibleToasts = { maxVisibleToasts }
389+ />
390+ ) ) }
391+ </ View >
392+ </ InsetsContainer >
393+ </ ToasterContext . Provider >
394+ </ ToastConfigContext . Provider >
326395 ) ;
327396}
328397
@@ -359,3 +428,18 @@ export function useToast() {
359428 isToastVisible : context . isToastVisible ,
360429 } ;
361430}
431+
432+ /**
433+ * Hook to access global toast configuration
434+ *
435+ * @returns Global toast configuration or undefined if not set
436+ *
437+ * @example
438+ * ```tsx
439+ * const globalConfig = useToastConfig();
440+ * // Use globalConfig.variant, globalConfig.placement, etc.
441+ * ```
442+ */
443+ export function useToastConfig ( ) : ToastGlobalConfig | undefined {
444+ return useContext ( ToastConfigContext ) ;
445+ }
0 commit comments