|
import { get } from 'svelte/store'; |
|
import { clientWritable } from './internal/helpers.js'; |
|
let toastsCounter = 0; |
|
function createToastState() { |
|
const toasts = clientWritable([]); |
|
const heights = clientWritable([]); |
|
function addToast(data) { |
|
toasts.update((prev) => [data, ...prev]); |
|
} |
|
function create(data) { |
|
const { message, ...rest } = data; |
|
const id = typeof data?.id === 'number' || (data.id && data.id?.length > 0) |
|
? data.id |
|
: toastsCounter++; |
|
const dismissable = data.dismissable === undefined ? true : data.dismissable; |
|
const type = data.type === undefined ? 'default' : data.type; |
|
const $toasts = get(toasts); |
|
const alreadyExists = $toasts.find((toast) => { |
|
return toast.id === id; |
|
}); |
|
if (alreadyExists) { |
|
toasts.update((prev) => prev.map((toast) => { |
|
if (toast.id === id) { |
|
return { |
|
...toast, |
|
...data, |
|
id, |
|
title: message, |
|
dismissable, |
|
type, |
|
updated: true |
|
}; |
|
} |
|
return { |
|
...toast, |
|
updated: false |
|
}; |
|
})); |
|
} |
|
else { |
|
addToast({ ...rest, id, title: message, dismissable, type }); |
|
} |
|
return id; |
|
} |
|
function dismiss(id) { |
|
if (id === undefined) { |
|
toasts.update((prev) => prev.map((toast) => ({ ...toast, dismiss: true }))); |
|
return; |
|
} |
|
toasts.update((prev) => prev.map((toast) => (toast.id === id ? { ...toast, dismiss: true } : toast))); |
|
return id; |
|
} |
|
function remove(id) { |
|
if (id === undefined) { |
|
toasts.set([]); |
|
return; |
|
} |
|
toasts.update((prev) => prev.filter((toast) => toast.id !== id)); |
|
return id; |
|
} |
|
function message(message, data) { |
|
return create({ ...data, type: 'default', message }); |
|
} |
|
function error(message, data) { |
|
return create({ ...data, type: 'error', message }); |
|
} |
|
function success(message, data) { |
|
return create({ ...data, type: 'success', message }); |
|
} |
|
function info(message, data) { |
|
return create({ ...data, type: 'info', message }); |
|
} |
|
function warning(message, data) { |
|
return create({ ...data, type: 'warning', message }); |
|
} |
|
function loading(message, data) { |
|
return create({ ...data, type: 'loading', message }); |
|
} |
|
function promise(promise, data) { |
|
if (!data) { |
|
|
|
return; |
|
} |
|
let id = undefined; |
|
if (data.loading !== undefined) { |
|
id = create({ |
|
...data, |
|
promise, |
|
type: 'loading', |
|
message: data.loading |
|
}); |
|
} |
|
const p = promise instanceof Promise ? promise : promise(); |
|
let shouldDismiss = id !== undefined; |
|
p.then((response) => { |
|
|
|
|
|
if (response && typeof response.ok === 'boolean' && !response.ok) { |
|
shouldDismiss = false; |
|
const message = typeof data.error === 'function' |
|
? |
|
data.error(`HTTP error! status: ${response.status}`) |
|
: data.error; |
|
create({ id, type: 'error', message }); |
|
} |
|
else if (data.success !== undefined) { |
|
shouldDismiss = false; |
|
const message = |
|
|
|
typeof data.success === 'function' ? data.success(response) : data.success; |
|
create({ id, type: 'success', message }); |
|
} |
|
}) |
|
.catch((error) => { |
|
if (data.error !== undefined) { |
|
shouldDismiss = false; |
|
const message = |
|
|
|
typeof data.error === 'function' ? data.error(error) : data.error; |
|
create({ id, type: 'error', message }); |
|
} |
|
}) |
|
.finally(() => { |
|
if (shouldDismiss) { |
|
|
|
dismiss(id); |
|
id = undefined; |
|
} |
|
data.finally?.(); |
|
}); |
|
return id; |
|
} |
|
function custom(component, data) { |
|
const id = data?.id || toastsCounter++; |
|
create({ component, id, ...data }); |
|
return id; |
|
} |
|
function removeHeight(id) { |
|
heights.update((prev) => prev.filter((height) => height.toastId !== id)); |
|
} |
|
function setHeight(data) { |
|
const exists = get(heights).find((el) => el.toastId === data.toastId); |
|
if (exists === undefined) { |
|
heights.update((prev) => [data, ...prev]); |
|
return; |
|
} |
|
heights.update((prev) => prev.map((el) => { |
|
if (el.toastId === data.toastId) { |
|
return data; |
|
} |
|
else { |
|
return el; |
|
} |
|
})); |
|
} |
|
function reset() { |
|
toasts.set([]); |
|
heights.set([]); |
|
} |
|
return { |
|
|
|
create, |
|
addToast, |
|
dismiss, |
|
remove, |
|
message, |
|
error, |
|
success, |
|
info, |
|
warning, |
|
loading, |
|
promise, |
|
custom, |
|
removeHeight, |
|
setHeight, |
|
reset, |
|
|
|
toasts, |
|
heights |
|
}; |
|
} |
|
export const toastState = createToastState(); |
|
|
|
function toastFunction(message, data) { |
|
return toastState.create({ |
|
message, |
|
...data |
|
}); |
|
} |
|
const basicToast = toastFunction; |
|
|
|
export const toast = Object.assign(basicToast, { |
|
success: toastState.success, |
|
info: toastState.info, |
|
warning: toastState.warning, |
|
error: toastState.error, |
|
custom: toastState.custom, |
|
message: toastState.message, |
|
promise: toastState.promise, |
|
dismiss: toastState.dismiss, |
|
loading: toastState.loading |
|
}); |
|
export const useEffect = (subscribe) => ({ subscribe }); |
|
|