Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 91 additions & 54 deletions dev/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,85 @@ import toast, { Toaster } from '../../src';
const makePromise = (): Promise<string> => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const toss = Math.random()
if (toss > 0.5) resolve('Successful!')
reject('Something went wrong!')
}, 2000)
})
}
const toss = Math.random();
if (toss > 0.5) resolve('Successful!');
reject('Something went wrong!');
}, 2000);
});
};

const App: Component = () => {
const popBlank = () => toast('Blank Toast');
const popSuccess = () => toast.success('Success!', { duration: Infinity });
const popError = () => toast.error('Error!', { duration: Infinity });
const popLoading = () => toast.loading('Loading...');
const popPromise = () => toast.promise(makePromise(), {
loading: <span class="promise-txt">Loading Promise</span>,
success: msg => <span class="promise-txt">{msg}</span>,
error: err => <span class="promise-txt">{err}</span>
});
const popCustom = () => toast.success('Add Custom Styles', {
iconTheme: {
primary: '#ea580c',
secondary: '#ffedd5'
},
className: "border-2 border-orange-800",
style: {
color: '#c2410c',
background: '#ffedd5'
},
duration: Infinity
});
const popTimer = () => toast.custom((t) => {
const [life, setLife] = createSignal(100)

createEffect(() => {
if (t.paused) return;
const interval = setInterval(() => {
console.log(t.paused)
setLife(l => l - 0.5)
}, 10)
const popPromise = () =>
toast.promise(makePromise(), {
loading: <span class="promise-txt">Loading Promise</span>,
success: (msg) => <span class="promise-txt">{msg}</span>,
error: (err) => <span class="promise-txt">{err}</span>,
});
const popCustom = () =>
toast.success('Add Custom Styles', {
iconTheme: {
primary: '#ea580c',
secondary: '#ffedd5',
},
className: 'border-2 border-orange-800',
style: {
color: '#c2410c',
background: '#ffedd5',
},
duration: Infinity,
});
const popTimer = () =>
toast.custom(
(t) => {
const [life, setLife] = createSignal(100);

onCleanup(() => clearInterval(interval))
})
createEffect(() => {
if (t.paused) return;
const interval = setInterval(() => {
console.log(t.paused);
setLife((l) => l - 0.5);
}, 10);

return (
<div class="bg-pink-100 shadow-md px-4 py-3 rounded overflow-hidden relative text-pink-700">
<div style={{width: `${life()}%`}} class="bg-pink-200 h-full absolute top-0 left-0" ></div>
<span class="relative" >Timer In The Background</span>
</div>
)
}, {
duration: 2000,
unmountDelay: 1000
});
onCleanup(() => clearInterval(interval));
});

return (
<div class="bg-pink-100 shadow-md px-4 py-3 rounded overflow-hidden relative text-pink-700">
<div style={{ width: `${life()}%` }} class="bg-pink-200 h-full absolute top-0 left-0"></div>
<span class="relative">Timer In The Background</span>
</div>
);
},
{
duration: 2000,
unmountDelay: 1000,
}
);

const [toggle, setToggle] = createSignal(false);

const closeAll = () => toast.dismiss();
return (
<div class="px-6">
<Toaster position="top-center" />
<Toaster
position="top-center"
toastOptions={{
iconTheme: toggle()
? {
primary: '#ea580c',
secondary: '#ffedd5',
}
: {
primary: '#5858ff',
secondary: '#ffedd5',
},
}}
/>
<button onClick={() => setToggle((t) => !t)}>Toggle Theme</button>
<h1>Solid Toast Examples</h1>
<div
style={{
Expand All @@ -70,15 +92,30 @@ const App: Component = () => {
gap: '0.5rem',
}}
>
<button class={"blank"} onClick={popBlank}>Blank Toast</button>
<button class={"success"} onClick={popSuccess}>Success Toast</button>
<button class={"error"} onClick={popError}>Error Toast</button>
<button class={"loading"} onClick={popLoading}>Loading Toast</button>
<button class={"promise"} onClick={popPromise}>Promise Toast</button>
<button class={"custom"} onClick={popCustom}>Custom Styles</button>
<button class={"timer"} onClick={popTimer}>Toast Timer</button>
<button class={"close"} onClick={closeAll}>Close all toasts</button>

<button class={'blank'} onClick={popBlank}>
Blank Toast
</button>
<button class={'success'} onClick={popSuccess}>
Success Toast
</button>
<button class={'error'} onClick={popError}>
Error Toast
</button>
<button class={'loading'} onClick={popLoading}>
Loading Toast
</button>
<button class={'promise'} onClick={popPromise}>
Promise Toast
</button>
<button class={'custom'} onClick={popCustom}>
Custom Styles
</button>
<button class={'timer'} onClick={popTimer}>
Toast Timer
</button>
<button class={'close'} onClick={closeAll}>
Close all toasts
</button>
</div>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions src/components/ToastBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const ToastBar: Component<ToastBarProps> = (props) => {
{
duration: 350,
fill: 'forwards',
easing: 'cubic-bezier(.21,1.02,.73,1)'
easing: 'cubic-bezier(.21,1.02,.73,1)',
}
);
} else {
Expand All @@ -30,7 +30,7 @@ export const ToastBar: Component<ToastBarProps> = (props) => {
{
duration: 400,
fill: 'forwards',
easing: 'cubic-bezier(.06,.71,.55,1)'
easing: 'cubic-bezier(.06,.71,.55,1)',
}
);
}
Expand Down
6 changes: 3 additions & 3 deletions src/components/ToastContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createMemo, onMount, Component } from 'solid-js';
import { ToastContainerProps } from '../';
import { defaultToastOptions, dispatch } from '../core';
import { ActionType, resolveValue } from '../types';
import { resolveValue } from '../types';
import { getToastWrapperStyles, getWrapperYAxisOffset, updateToastHeight } from '../util';
import { ToastBar } from './ToastBar';

Expand Down Expand Up @@ -30,13 +30,13 @@ export const ToastContainer: Component<ToastContainerProps> = (props) => {
class={props.toast.visible ? 'sldt-active' : ''}
onMouseEnter={() =>
dispatch({
type: ActionType.START_PAUSE,
type: 'start_pause',
time: Date.now(),
})
}
onMouseLeave={() =>
dispatch({
type: ActionType.END_PAUSE,
type: 'end_pause',
time: Date.now(),
})
}
Expand Down
49 changes: 29 additions & 20 deletions src/core/store.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { State, Action, ActionType, Toast } from '../types';
import { State, Toast, Action, ToastOptions } from '../types';
import { createStore, produce as p } from 'solid-js/store';

const [initOptions, setInitOptions] = createStore<{
options: ToastOptions[];
}>({
options: [],
});

const [store, setStore] = createStore<State>({
toasts: [],
pausedAt: undefined,
Expand All @@ -18,7 +24,7 @@ export const createTimers = () => {
if (durationLeft <= 0) {
if (toast.visible) {
dispatch({
type: ActionType.DISMISS_TOAST,
type: 'dismiss',
toastId: toast.id,
});
}
Expand All @@ -27,7 +33,7 @@ export const createTimers = () => {

return setTimeout(() => {
dispatch({
type: ActionType.DISMISS_TOAST,
type: 'dismiss',
toastId: toast.id,
});
}, durationLeft);
Expand All @@ -44,7 +50,7 @@ const scheduleRemoval = (toastId: string, unmountDelay: number) => {
const timeout = setTimeout(() => {
removalQueue.delete(toastId);
dispatch({
type: ActionType.REMOVE_TOAST,
type: 'remove',
toastId,
});
}, unmountDelay);
Expand All @@ -60,13 +66,13 @@ const unscheduleRemoval = (toastId: string) => {

export const dispatch = (action: Action) => {
switch (action.type) {
case ActionType.ADD_TOAST:
case 'add':
setStore('toasts', (t) => {
const toasts = t as Toast[];
return [action.toast, ...toasts];
});
break;
case ActionType.DISMISS_TOAST:
case 'dismiss':
const { toastId } = action;
const toasts = store.toasts;

Expand All @@ -90,7 +96,7 @@ export const dispatch = (action: Action) => {
}

break;
case ActionType.REMOVE_TOAST:
case 'remove':
if (!action.toastId) {
setStore('toasts', []);
break;
Expand All @@ -100,7 +106,7 @@ export const dispatch = (action: Action) => {
return toasts.filter((t) => t.id !== action.toastId);
});
break;
case ActionType.UPDATE_TOAST:
case 'update':
if (action.toast.id) {
unscheduleRemoval(action.toast.id);
}
Expand All @@ -117,20 +123,22 @@ export const dispatch = (action: Action) => {
}
);
break;
case ActionType.UPSERT_TOAST:
case 'upsert':
store.toasts.find((t) => t.id === action.toast.id)
? dispatch({ type: ActionType.UPDATE_TOAST, toast: action.toast })
: dispatch({ type: ActionType.ADD_TOAST, toast: action.toast });
? dispatch({ type: 'update', toast: action.toast })
: dispatch({ type: 'add', toast: action.toast });
break;
case ActionType.START_PAUSE:
setStore(p((s) => {
s.pausedAt = Date.now();
s.toasts.forEach((t) => {
t.paused = true;
});
}));
case 'start_pause':
setStore(
p((s) => {
s.pausedAt = Date.now();
s.toasts.forEach((t) => {
t.paused = true;
});
})
);
break;
case ActionType.END_PAUSE:
case 'end_pause':
const pauseInterval = action.time - (store.pausedAt || 0);
setStore(
p((s) => {
Expand All @@ -145,4 +153,5 @@ export const dispatch = (action: Action) => {
}
};

export { store };
export const initOptionsDispatch = (action: Action) => {};
export { store, initOptions };
11 changes: 5 additions & 6 deletions src/core/toast.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createRoot, createSignal, untrack } from 'solid-js';
import { ToasterProps, Message, ToastType, ToastOptions, Toast, ToastHandler, ActionType } from '../types';
import { createRoot, createSignal } from 'solid-js';
import { ToasterProps, Message, ToastType, ToastOptions, Toast, ToastHandler } from '../types';
import { defaultToasterOptions, defaultToastOptions, defaultTimeouts } from './defaults';
import { generateID } from '../util';
import { dispatch, store } from './store';
Expand Down Expand Up @@ -35,13 +35,12 @@ const createToastCreator =
return createRoot(() => {
const existingToast = store.toasts.find((t) => t.id === options.id) as Toast;
const toast = createToast(message, type, { ...existingToast, duration: undefined, ...options });
dispatch({ type: ActionType.UPSERT_TOAST, toast });
dispatch({ type: 'upsert', toast });
return toast.id;
});
};

const toast = (message: Message, opts?: ToastOptions) => createToastCreator('blank')(message, opts);
const test = untrack(() => toast);

toast.error = createToastCreator('error');
toast.success = createToastCreator('success');
Expand All @@ -50,7 +49,7 @@ toast.custom = createToastCreator('custom');

toast.dismiss = (toastId?: string) => {
dispatch({
type: ActionType.DISMISS_TOAST,
type: 'dismiss',
toastId,
});
};
Expand Down Expand Up @@ -86,7 +85,7 @@ toast.promise = <T>(

toast.remove = (toastId?: string) => {
dispatch({
type: ActionType.REMOVE_TOAST,
type: 'remove',
toastId,
});
};
Expand Down
Loading