Skip to content

Commit

Permalink
feat: support show toast using promise
Browse files Browse the repository at this point in the history
  • Loading branch information
nhanluongoe committed Jan 9, 2024
1 parent 55cee5c commit c9f39fc
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 5 deletions.
43 changes: 39 additions & 4 deletions src/core/store.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import React from 'react';
import { Toast, ToastsOptions } from './types';

export const TOAST_EXPIRE_DISMISS_DELAY = 1000;
const TOAST_LIMIT = 3;

type ActionType = {
ADD_TOAST: 'ADD_TOAST';
REMOVE_TOAST: 'REMOVE_TOAST';
DISMISS_TOAST: 'DISMISS_TOAST';
UPSERT_TOAST: 'UPSERT_TOAST';
UPDATE_TOAST: 'UPDATE_TOAST';
PAUSE: 'PAUSE';
RESUME: 'RESUME';
};
Expand All @@ -22,6 +27,14 @@ type Action =
toastId?: Toast['id'];
type: ActionType['REMOVE_TOAST'];
}
| {
type: ActionType['UPSERT_TOAST'];
toast: Toast;
}
| {
type: ActionType['UPDATE_TOAST'];
toast: Partial<Toast>;
}
| {
type: ActionType['PAUSE'];
time: number;
Expand All @@ -39,9 +52,6 @@ interface State {

const toastTimeouts = new Map<Toast['id'], ReturnType<typeof setTimeout>>();

export const TOAST_EXPIRE_DISMISS_DELAY = 0;
const TOAST_LIMIT = 3;

const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) {
return;
Expand All @@ -58,6 +68,13 @@ const addToRemoveQueue = (toastId: string) => {
toastTimeouts.set(toastId, timeout);
};

const clearFromRemoveQueue = (toastId: string) => {
const timeout = toastTimeouts.get(toastId);
if (timeout) {
clearTimeout(timeout);
}
};

export const reducer = (state: State, action: Action): State => {
switch (action.type) {
case 'ADD_TOAST': {
Expand All @@ -70,7 +87,6 @@ export const reducer = (state: State, action: Action): State => {
case 'DISMISS_TOAST': {
const { toastId } = action;

// ! Side effects ! - This could be execrated into a dismissToast() action, but I'll keep it here for simplicity
if (toastId) {
addToRemoveQueue(toastId);
} else {
Expand Down Expand Up @@ -107,6 +123,25 @@ export const reducer = (state: State, action: Action): State => {
};
}

case 'UPSERT_TOAST':
const { toast } = action;
return state.toasts.find((t) => t.id === toast.id)
? reducer(state, { type: 'UPDATE_TOAST', toast })
: reducer(state, { type: 'ADD_TOAST', toast });

case 'UPDATE_TOAST': {
if (action.toast.id) {
clearFromRemoveQueue(action.toast.id);
}

return {
...state,
toasts: state.toasts.map((t) =>
t.id === action.toast.id ? { ...t, ...action.toast } : t
),
};
}

case 'PAUSE': {
return {
...state,
Expand Down
23 changes: 22 additions & 1 deletion src/core/use-toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { dispatch, useStore } from './store';
import {
Toast,
ToastArg,
ToastOptions,
ToasterType,
ToastsOptions,
isFunction,
Expand Down Expand Up @@ -47,7 +48,7 @@ function createHandler(type?: ToasterType) {
return (options: ToastArg) => {
const toast = createToast(type, options);
dispatch({
type: 'ADD_TOAST',
type: 'UPSERT_TOAST',
toast,
});
return toast.id;
Expand All @@ -59,6 +60,26 @@ toast.error = createHandler('error');
toast.success = createHandler('success');
toast.loading = createHandler('loading');

toast.promise = <T>(
promise: Promise<T>,
content: {
loading: ToastOptions;
success: ToastOptions;
error: ToastOptions;
}
) => {
const id = toast.loading(content.loading);
promise
.then((p) => {
toast.success({ ...content.success, id });
return p;
})
.catch(() => {
toast.error({ ...content.error, id });
});
return promise;
};

toast.dismiss = (toastId?: string) => {
dispatch({
type: 'DISMISS_TOAST',
Expand Down

0 comments on commit c9f39fc

Please sign in to comment.