feat(ui): add updateDescription flag to toast API

If false, when updating a toast, the description is left alone. The count will still tick up.
This commit is contained in:
psychedelicious 2024-05-22 07:20:58 +10:00
parent 4a394c60cf
commit 57743239d7

View File

@ -22,6 +22,18 @@ type ToastArg = ToastConfig & {
* // second toast: 'Hello (2)' * // second toast: 'Hello (2)'
*/ */
withCount?: boolean; withCount?: boolean;
/**
* Whether to update the description when updating the toast. Defaults to true.
* @example
* // updateDescription: true
* toast({ title: 'Hello', description: 'Foo' }); // Foo
* toast({ title: 'Hello', description: 'Bar' }); // Bar
* @example
* // updateDescription: false
* toast({ title: 'Hello', description: 'Foo' }); // Foo
* toast({ title: 'Hello', description: 'Bar' }); // Foo
*/
updateDescription?: boolean;
}; };
type ToastInternalState = { type ToastInternalState = {
@ -48,6 +60,7 @@ const getGetState = (id: string) => () => $toastMap.get()[id] ?? null;
/** /**
* Creates a toast with the given config. If the toast with the same id already exists, it will be updated. * Creates a toast with the given config. If the toast with the same id already exists, it will be updated.
* When a toast is updated, its title, description, status and duration will be overwritten by the new config. * When a toast is updated, its title, description, status and duration will be overwritten by the new config.
* Use `updateDescription: false` to keep the description when updating.
* Set duration to `null` to make the toast persistent. * Set duration to `null` to make the toast persistent.
* @param arg The toast config. * @param arg The toast config.
* @returns An object with methods to get the toast state, close the toast and check if the toast is active * @returns An object with methods to get the toast state, close the toast and check if the toast is active
@ -61,17 +74,20 @@ export const toast = (arg: ToastArg): ToastApi => {
if (arg.withCount === undefined) { if (arg.withCount === undefined) {
arg.withCount = true; arg.withCount = true;
} }
if (arg.updateDescription === undefined) {
arg.updateDescription = true;
}
let state = $toastMap.get()[arg.id]; let state = $toastMap.get()[arg.id];
if (!state) { if (!state) {
// First time caller, create and set the state // First time caller, create and set the state
state = { id, config: parseConfig(id, arg, 1), count: 1 }; state = { id, config: parseConfig(null, id, arg, 1), count: 1 };
$toastMap.setKey(id, state); $toastMap.setKey(id, state);
// Create the toast // Create the toast
toastApi(state.config); toastApi(state.config);
} else { } else {
// This toast is already active, update its state // This toast is already active, update its state
state.count += 1; state.count += 1;
state.config = parseConfig(id, arg, state.count); state.config = parseConfig(state, id, arg, state.count);
$toastMap.setKey(id, state); $toastMap.setKey(id, state);
// Update the toast itself // Update the toast itself
toastApi.update(id, state.config); toastApi.update(id, state.config);
@ -81,18 +97,26 @@ export const toast = (arg: ToastArg): ToastApi => {
/** /**
* Give a toast id, arg and current count, returns the parsed toast config (including dynamic title and description) * Give a toast id, arg and current count, returns the parsed toast config (including dynamic title and description)
* @param state The current state of the toast or null if it doesn't exist
* @param id The id of the toast * @param id The id of the toast
* @param arg The arg passed to the toast function * @param arg The arg passed to the toast function
* @param count The current call count of the toast * @param count The current call count of the toast
* @returns The parsed toast config * @returns The parsed toast config
*/ */
const parseConfig = (id: string, arg: ToastArg, count: number): ToastConfig => { const parseConfig = (state: ToastInternalState | null, id: string, arg: ToastArg, count: number): ToastConfig => {
const title = arg.withCount && count > 1 ? `${arg.title} (${count})` : arg.title;
const onCloseComplete = () => { const onCloseComplete = () => {
$toastMap.setKey(id, undefined); $toastMap.setKey(id, undefined);
if (arg.onCloseComplete) { if (arg.onCloseComplete) {
arg.onCloseComplete(); arg.onCloseComplete();
} }
}; };
return { ...arg, title, onCloseComplete }; const title = arg.withCount && count > 1 ? `${arg.title} (${count})` : arg.title;
const description = !arg.updateDescription && state ? state.config.description : arg.description;
const config: ToastConfig = {
...arg,
title,
description,
onCloseComplete,
};
return config;
}; };